문제

사용하는 방법이 있습니까? foreach 컬렉션을 통해 뒤로 또는 완전히 임의의 순서로 반복하는 루프?

도움이 되었습니까?

해결책

다른 답변이 언급했듯이 Reverse() 확장 방법 순서로 시퀀스를 열거 할 수 있습니다.

임의의 열거 확장 방법은 다음과 같습니다.

public static IEnumerable<T> OrderRandomly<T>(this IEnumerable<T> sequence)
{
    Random random = new Random();
    List<T> copy = sequence.ToList();

    while (copy.Count > 0)
    {
        int index = random.Next(copy.Count);
        yield return copy[index];
        copy.RemoveAt(index);
    }
}

사용량은 다음과 같습니다.

foreach (int n in Enumerable.Range(1, 10).OrderRandomly())
    Console.WriteLine(n);

다른 팁

사용 System.Linq 당신은 할 수 있습니다 ...

// List<...> list;
foreach (var i in list.Reverse())
{
}

임의 순서를 위해 무작위로 사용해야합니다. list.OrderBy (또 다른 LINQ 확장)와 해당 순서 목록을 반복하십시오.

var rnd = new Random();
var randomlyOrdered = list.OrderBy(i => rnd.Next());
foreach (var i in randomlyOrdered)
{
}

직접 할 수있는 방법이 없다고 생각하지만 거의 as good 새 컬렉션을 반환하는 확장 방법을 사용하려면 TH를 통해 yield return 예어. 이들은 기존 도서관에서 나올 수 있습니다. 다른 사람들은 LINQ에 a가 있다고 지적했습니다 Reverse 방법과 같은 것들 OrderBy 또한 작동합니다.

예 : LINQ 확장 방법을 사용하는 경우 Reverse() ~에 IEnumerable<T>, 사용하는 yield return 컬렉션을 역순으로 제공하려면 foreach(var myThing in myCollection.Reverse()) 컬렉션을 통해 역순으로 열거됩니다.

중요한: yield return 핵심입니다. "이 컬렉션을 열거 할 때 물건을 가져 오십시오."를 의미합니다. 단지 구성의 대안과는 반대로 a 새로운, 비효율적이며 부작용이있는 역전 된 컬렉션은 역전 된 컬렉션입니다.

나는 실제로 LINQ와의 CFEDUKE 접근법을 좋아했고 그것이 내 마음을 미끄러 져 버그를 냈다. 이전 예제에 추가합니다. LINQ의 도움으로 홀수 및 심지어 반복을하고 싶다면 사용할 수 있습니다.

// Even
foreach (var i in ints.FindAll(number => number % 2 == 0))
{
      Console.WriteLine(i);
}

// Odd
foreach (var i in ints.FindAll(number => number % 2 != 0))
{
      Console.WriteLine(i);
}

사용 IList<T> ~로부터 C5 일반 수집 라이브러리, 리버스 반복은 확장보다는 기능입니다.

foreach (var i in list.Reverse())
{
}

또한 사용할 수 있습니다 Shuffle() 무작위 주문을받는 방법 :

var listClone = (IList<T>) list.Clone();
listClone.Shuffle();
foreach (var i in listClone)
{
}

C# 2.0 기준으로 수율 키워드를 사용하여 사용자 정의 반복기를 쉽게 구현할 수 있습니다. MSDN에서 수율 키워드에 대한 자세한 내용을 읽을 수 있습니다. http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

수익률을 루프 내부에서 값을 반환 할 수있는 능력으로 생각할 수 있지만, 위의 링크를 참조하여 그들이 무엇인지, 무엇을 할 수 있는지에 대한 전체 설명을 참조해야합니다.

나는 몇 가지 사용자 정의 반복자를 구현하는 방법에 대한 짧은 예를 썼습니다. 확장 방법으로 구현했습니다 (http://msdn.microsoft.com/en-us/library/bb383977.aspx) 코드를 조금 더 스트림으로 늘어선 상태로 만들고 배열 이니셜 라이저도 사용합니다.http://msdn.microsoft.com/en-us/library/aa664573.aspx) 정수 목록의 초기 값을 설정합니다.

사용자 지정 반복기 구현에는 확장 방법이나 배열 이니셜 라이저가 필요하지 않지만 C# 3.0의 멋진 기능이므로 클리너 코드를 작성하는 데 도움이됩니다.

여기 내 예입니다. 그것은 홀수 숫자, 짝수 숫자, 반전 또는 완전한 임의의 방식으로 숫자를 반환하여 정수 목록을 반복하는 방법을 보여줍니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> ints = 
                new List<int> { 1,2,3,4,5,6,7,8,9,10};

            Console.WriteLine("Iterating over Odd numbers only.");
            foreach (int i in ints.Odd())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over Even numbers only.");
            foreach (int i in ints.Even())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over the list in reversed order.");
            foreach (int i in ints.Reversed())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over the list in random order.");
            foreach (int i in ints.Random())
            {
                Console.WriteLine(i);
            }

            Console.ReadLine();
        }
    }

    public static class ListExtensions
    {
        /// <summary>
        /// Iterates over the list only returns even numbers
        /// </summary>
        /// <param name="list"></param>
        public static IEnumerable<int> Even(this List<int> list)
        {
            foreach (var i in list)
            {
                if (i % 2 == 0)
                 {
                    yield return i;
                }
           }
        }

        /// <summary>
        /// Iterates over the list only returns odd numbers
        /// </summary>
        public static IEnumerable<int> Odd(this List<int> list)
        {
            foreach (var i in list)
            {
                if (i % 2 != 0)
                {
                    yield return i;
                }
            }
        }

        /// <summary>
        /// Iterates over the list in reversed order
        /// </summary>
        public static IEnumerable<int> Reversed(this List<int> list)
        {
            for (int i = list.Count; i >= 0; i--)
            {
                yield return i;
            }
        }

        /// <summary>
        /// Iterates over the list in random order
        /// </summary>
        public static IEnumerable<int> Random(this List<int> list)
        {
            // Initialize a random number generator with a seed.
            System.Random rnd =
                new Random((int)DateTime.Now.Ticks);

            // Create a list to keep track of which indexes we've
            // already returned
            List<int> visited =
                new List<int>();

            // loop until we've returned the value of all indexes
            // in the list
            while (visited.Count < list.Count)
            {
                int index =
                    rnd.Next(0, list.Count);

                // Make sure we've not returned it already
                if (!visited.Contains(index))
                {
                    visited.Add(index);
                    yield return list[index];
                }
            }
        }
    }
}

자신의 비교기를 공급하여 목록을 정렬하고 그 목록을 반복 할 수 있습니다.

거꾸로 할 수 있습니다.

for (int i=col.count-1; i>0; i--){ 
      DoSomething ( col.item[i]) ;
}

정확한 구문에 대해서는 확실하지 않지만 이것이 패러다임입니다.

완전히 임의의 순서와 관련하여 IT의 색인을 통해 수집 요소에 액세스 할 수 있습니다. 모든 항목에 도달하려면 이미 처리 한 요소 (아마도 컬렉션을 복사 한 다음 액세스 후 요소를 제거함으로써)를 추적해야합니다.

편집 : 무작위 액세스에 대한 자세한 내용은 무작위 액세스에 대한 코드가 다음과 같은 것처럼 보일 수 있습니다.

 collection c = originalCollection;
 while (c.count > 0) {
     int i = randomNumber(seed) mod c.count
     element d = c[i];
     c.remove(d);
     DoSomething(d);
}

컬렉션을 방해하고 그것에 대해 방해하고 싶습니까?

그렇다면 이것을 시도하십시오.

Random rand = new Random(Environment.TickCount);

test.Sort((string v1, string v2) => {
                if (v1.Equals(v2))
                {
                    return 0;
                }

                int x = rand.Next();
                int y = rand.Next();

                if (x == y)
                {
                    return 0;
                }
                else if (x > y)
                {
                    return 1;
                }

                return -1; 
            });

for (string item in test)
{
  Console.WriteLn(item);
}
// Note that test is List<string>;

C# 언어 사양을 읽음으로써, Foreach 반복 문은 getEnumerator () 함수가 정의되어 있으면 반복되는 구조/클래스/인터페이스에 따라 다릅니다. getEnumerator ()에 의해 반환 된 객체는 멤버 함수로 정의 된 movenext ()가 있어야합니다. movenext ()는 첫 번째 호출의 목록에서 "첫 번째"객체에 액세스 한 다음 후속 통화에서 "다음"으로 정의되어 목록에 더 이상 요소가 존재하지 않을 때까지 True를 반환하여 False를 반환합니다.

Domenic 기능은 2.0 버전의 사양에 나타나며,이 목적에 유용한 것으로 보입니다. 버전 1.1의 경우 유일한 옵션은 기본에서 새 구조/클래스/인터페이스를 도출하고 getEnumerator ()를 재정의하여 새 IENUMERATOR를 반환하는 것입니다. 후속 수집 요소.

내 자신의 권장 사항은 인덱스 된 컬렉션을 사용한 다음 적절한 인덱스 계산이있는 루프를 사용하는 것입니다 (필요한 경우 임의의 숫자 생성기를 사용할 수 있습니다. 정수 배열 또는 동일한 인덱스 값이 아닌지 확인하기위한 다른 기술이 있습니다. 실제 연습 에서이 작업을 수행 해야하는 경우 두 번 사용합니다.

무작위 주문을 사용하십시오
http://www.dailycoding.com/..using_linq.aspx

List<Employee> list = new List<Employee>();

list.Add(new Employee { Id = 1, Name = "Davolio Nancy" });
list.Add(new Employee { Id = 2, Name = "Fuller Andrew" });
list.Add(new Employee { Id = 3, Name = "Leverling Janet" });
list.Add(new Employee { Id = 4, Name = "Peacock Margaret" });
list.Add(new Employee { Id = 5, Name = "Buchanan Steven" });
list.Add(new Employee { Id = 6, Name = "Suyama Michael" });
list.Add(new Employee { Id = 7, Name = "King Robert" });
list.Add(new Employee { Id = 8, Name = "Callahan Laura" });
list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" });

list = list.OrderBy(emp => Guid.NewGuid()).ToList();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top