문제
나는 다음을 사용할 수 있다는 것을 안다. for
문을 실행하고 동일한 효과를 얻을 수 있지만 foreach
C#의 루프?
해결책
목록으로 작업 할 때 (직접 인덱싱) for
고리.
편집 : 그것은 일반적으로 당신이있을 때를 의미합니다 할 수 있는 사용하려면 for
루프,이 작업에 대한 올바른 방법 일 수 있습니다. 또한,만큼 foreach
사산으로 구현되며, 구조 자체는 요소 인덱스 및 반복 순서와 무관 한 루프를 표현하기 위해 구축되었으며, 이는 특히 중요합니다. 병렬 프로그래밍. 그것은이다 내 의견 주문에 의존하는 반복은 사용해서는 안됩니다 foreach
루핑을 위해.
다른 팁
.NET 3.5에있는 경우 다음을 수행 할 수 있습니다.
IEnumerable<int> enumerableThing = ...;
foreach (var x in enumerableThing.Reverse())
기본적으로 열거자를 통해 모든 것을 스택에 올려 놓고 역순으로 모든 것을 다시 튀어 나와야하기 때문에 그다지 효율적이지 않습니다.
직접적으로 명시적인 컬렉션 (예 : Ilist)이있는 경우 for
대신 루프.
.NET 2.0에 있고 for 루프를 사용할 수없는 경우 (예 : ienumerable이 있습니다) 자신의 역 함수를 작성하면됩니다. 이것은 작동해야합니다 :
static IEnumerable<T> Reverse<T>(IEnumerable<T> input)
{
return new Stack<T>(input);
}
이것은 아마도 명백하지 않은 행동에 의존합니다. 스택 생성자에게 ienumerable을 통과하면 반복을 반복하여 항목을 스택에 밀어 넣습니다. 그런 다음 스택을 통해 반복하면 물건을 역 순서로 다시 튀어 나옵니다.
이것과 .NET 3.5 Reverse()
확장 방법은 반환 품목을 절대 멈추지 않도록 ienumerable을 먹이면 분명히 폭발합니다.
280Z28이 말했듯이 IList<T>
그냥 인덱스를 사용해도 됩니다.확장 메서드에서 이를 숨길 수 있습니다.
public static IEnumerable<T> FastReverse<T>(this IList<T> items)
{
for (int i = items.Count-1; i >= 0; i--)
{
yield return items[i];
}
}
이 것보다 더 빠를 거예요 Enumerable.Reverse()
모든 데이터를 먼저 버퍼링합니다.(나는 믿지 않는다 Reverse
다음과 같은 방식으로 최적화가 적용되었습니다. Count()
않습니다.) 이 버퍼링은 처음 반복을 시작할 때 데이터가 완전히 읽혀진다는 것을 의미합니다. FastReverse
반복하는 동안 목록에 적용된 모든 변경 사항을 "확인"할 수 있습니다.(반복 사이에 여러 항목을 제거하면 중단됩니다.)
일반 시퀀스의 경우 역순으로 반복할 수 있는 방법이 없습니다. 시퀀스는 무한할 수 있습니다. 예를 들면 다음과 같습니다.
public static IEnumerable<T> GetStringsOfIncreasingSize()
{
string ret = "";
while (true)
{
yield return ret;
ret = ret + "x";
}
}
이를 반대로 반복하려고 하면 어떻게 될까요?
반복에 'foreach'를 사용하기 전에 'Reverse'방법으로 목록을 반대로 반전시킵니다.
myList.Reverse();
foreach( List listItem in myList)
{
Console.WriteLine(listItem);
}
목록을 사용하는 경우u003CT> ,이 코드를 사용할 수도 있습니다.
List<string> list = new List<string>();
list.Add("1");
list.Add("2");
list.Add("3");
list.Reverse();
이것은 목록 자체로 목록을 작성하는 메소드입니다.
이제 foreach :
foreach(string s in list)
{
Console.WriteLine(s);
}
출력은 다음과 같습니다.
3
2
1
때로는 인덱싱의 사치가 없거나 LINQ 쿼리의 결과를 뒤집기를 원하거나 소스 컬렉션을 수정하고 싶지 않을 수도 있습니다.이 중 하나라도 사실이라면 LINQ가 도움을 줄 수 있습니다.
LINQ를 선택한 익명 유형을 사용하는 LINQ 확장 방법은 LINQ OrderByDescending을위한 정렬 키를 제공합니다.
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source)
{
var transform = source.Select(
(o, i) => new
{
Index = i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
용법:
var eable = new[]{ "a", "b", "c" };
foreach(var o in eable.Invert())
{
Console.WriteLine(o);
}
// "c", "b", "a"
"반전"과 동의어이기 때문에 "반전"이라고 불리며 목록 리버스 구현으로 명확하게 변환 할 수 있습니다.
int32.minvalue 및 int32.maxvalue는 모든 종류의 수집 인덱스 범위를 벗어나기 때문에 주문 프로세스를 위해이를 활용할 수 있기 때문에 컬렉션의 특정 범위를 뒤집을 수 있습니다. 요소 인덱스가 주어진 범위 아래에있는 경우 int32.maxValue로 할당되어 OrderByDescending을 사용할 때 순서가 변경되지 않도록 지정됩니다. 순서 프로세스의 끝에 나타납니다. 주어진 범위 내의 모든 요소에는 정상 색인이 할당되며 그에 따라 역전됩니다.
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source, int index, int count)
{
var transform = source.Select(
(o, i) => new
{
Index = i < index ? Int32.MaxValue : i >= index + count ? Int32.MinValue : i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
용법:
var eable = new[]{ "a", "b", "c", "d" };
foreach(var o in eable.Invert(1, 2))
{
Console.WriteLine(o);
}
// "a", "c", "b", "d"
이러한 LINQ 구현의 성능 히트와 임시 목록을 사용하여 역전을위한 컬렉션을 래핑하는 것을 잘 모르겠습니다.
글을 쓰는 시점에서 나는 LINQ의 자체 역 구현을 알지 못했지만 여전히 재미있었습니다.https://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx
아니오.
그것은이다 수집 코드를 변경할 수있는 경우 가능합니다 이는 ienumerable 또는 ienumerable (예 : ILIST의 구현)을 구현합니다.
생성 반복자 예를 들어 다음과 같은 구현과 같이이 작업을 수행합니다. ienumerable 인터페이스 ( '항목'이이 샘플의 목록 필드라고 가정) :
public IEnumerator<TObject> GetEnumerator()
{
for (var i = items.Count - 1; i >= 0; i--)
{
yield return items[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
이 때문에 귀하의 목록은 목록을 통해 역순으로 반복합니다.
그냥 힌트 : 문서 내에서 목록 의이 특별한 행동을 명확하게 명시해야합니다 (스택이나 큐와 같은 자체 설명 클래스 이름을 선택함으로써 더 좋습니다).
멋진 대답에 약간의 정교함 존 스키트, 이것은 다재다능 할 수 있습니다 :
public static IEnumerable<T> Directional<T>(this IList<T> items, bool Forwards) {
if (Forwards) foreach (T item in items) yield return item;
else for (int i = items.Count-1; 0<=i; i--) yield return items[i];
}
그리고 AS를 사용하십시오
foreach (var item in myList.Directional(forwardsCondition)) {
.
.
}
이 코드를 사용했습니다
if (element.HasAttributes) {
foreach(var attr in element.Attributes().Reverse())
{
if (depth > 1)
{
elements_upper_hierarchy_text = "";
foreach (var ancest in element.Ancestors().Reverse())
{
elements_upper_hierarchy_text += ancest.Name + "_";
}// foreach(var ancest in element.Ancestors())
}//if (depth > 1)
xml_taglist_report += " " + depth + " " + elements_upper_hierarchy_text+ element.Name + "_" + attr.Name +"(" + attr.Name +")" + " = " + attr.Value + "\r\n";
}// foreach(var attr in element.Attributes().Reverse())
}// if (element.HasAttributes) {
이것은 꽤 잘 작동합니다
List<string> list = new List<string>();
list.Add("Hello");
list.Add("Who");
list.Add("Are");
list.Add("You");
foreach (String s in list)
{
Console.WriteLine(list[list.Count - list.IndexOf(s) - 1]);
}