[C#] C #에서 컬렉션 필터링

C #에서 컬렉션을 필터링하는 매우 빠른 방법을 찾고 있습니다. 나는 현재 일반적인 List <object> 컬렉션을 사용하고 있지만 더 나은 성능을 발휘한다면 다른 구조를 사용할 수 있습니다.

현재 새 List <object>를 만들고 원래 목록을 통해 반복하고 있습니다. 필터링 기준이 일치하면 새 목록에 사본을 넣습니다.

더 좋은 방법이 있습니까? 임시 목록이 필요하지 않도록 필터링 할 수있는 방법이 있습니까?



답변

C # 3.0을 사용하는 경우 linq를 더 잘 사용하고 더 우아하게 사용할 수 있습니다.

List<int> myList = GetListOfIntsFromSomewhere();

// This will filter out the list of ints that are > than 7, Where returns an
// IEnumerable<T> so a call to ToList is required to convert back to a List<T>.
List<int> filteredList = myList.Where( x => x > 7).ToList();

를 찾을 수 없으면 파일 상단에서 .Where가져와야 using System.Linq;합니다.


답변

다음은 Lambdas 및 LINQ 기반 목록 필터링을 보여주기 위해 함께 세 가지 다른 방법을 사용하는 일부 목록 필터링의 코드 블록 / 예입니다.

#region List Filtering

static void Main(string[] args)
{
    ListFiltering();
    Console.ReadLine();
}

private static void ListFiltering()
{
    var PersonList = new List<Person>();

    PersonList.Add(new Person() { Age = 23, Name = "Jon", Gender = "M" }); //Non-Constructor Object Property Initialization
    PersonList.Add(new Person() { Age = 24, Name = "Jack", Gender = "M" });
    PersonList.Add(new Person() { Age = 29, Name = "Billy", Gender = "M" });

    PersonList.Add(new Person() { Age = 33, Name = "Bob", Gender = "M" });
    PersonList.Add(new Person() { Age = 45, Name = "Frank", Gender = "M" });

    PersonList.Add(new Person() { Age = 24, Name = "Anna", Gender = "F" });
    PersonList.Add(new Person() { Age = 29, Name = "Sue", Gender = "F" });
    PersonList.Add(new Person() { Age = 35, Name = "Sally", Gender = "F" });
    PersonList.Add(new Person() { Age = 36, Name = "Jane", Gender = "F" });
    PersonList.Add(new Person() { Age = 42, Name = "Jill", Gender = "F" });

    //Logic: Show me all males that are less than 30 years old.

    Console.WriteLine("");
    //Iterative Method
    Console.WriteLine("List Filter Normal Way:");
    foreach (var p in PersonList)
        if (p.Gender == "M" && p.Age < 30)
            Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //Lambda Filter Method
    Console.WriteLine("List Filter Lambda Way");
    foreach (var p in PersonList.Where(p => (p.Gender == "M" && p.Age < 30))) //.Where is an extension method
        Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //LINQ Query Method
    Console.WriteLine("List Filter LINQ Way:");
    foreach (var v in from p in PersonList
                      where p.Gender == "M" && p.Age < 30
                      select new { p.Name, p.Age })
        Console.WriteLine(v.Name + " is " + v.Age);
}

private class Person
{
    public Person() { }
    public int Age { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
}

#endregion


답변

List<T>FindAll필터링을 수행하고 목록의 하위 집합을 반환 하는 메서드가 있습니다.

MSDN에는 훌륭한 코드 예제가 있습니다. http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx

편집 : 나는 LINQ와 Where()방법을 잘 이해하기 전에 이것을 썼습니다 . 오늘이 글을 쓰려면 위의 호르헤 언급 방법을 사용했을 것입니다. FindAll그래도 .NET 2.0 환경에 갇혀 있으면 이 방법이 여전히 작동합니다.


답변

IEnumerable을 사용하여 임시 목록이 필요하지 않습니다.

public IEnumerable<T> GetFilteredItems(IEnumerable<T> collection)
{
    foreach (T item in collection)
    if (Matches<T>(item))
    {
        yield return item;
    }
}

여기서 Matches는 필터 방법의 이름입니다. 그리고 당신은 이것을 다음과 같이 사용할 수 있습니다 :

IEnumerable<MyType> filteredItems = GetFilteredItems(myList);
foreach (MyType item in filteredItems)
{
    // do sth with your filtered items
}

필요한 경우 GetFilteredItems 함수를 호출하고 경우에 따라 필터링 된 컬렉션에서 모든 항목을 사용하지 않으면 성능이 약간 향상 될 수 있습니다.


답변

이를 위해 “List <>”클래스의 RemoveAll 메소드를 사용자 정의 “Predicate”클래스와 함께 사용할 수 있지만 코드를 정리하기 만하면됩니다. 네가 …하지만 네, 그것은 제 위치에 있으므로 임시 목록과 동일합니다.


답변

List 의 FindAll 메서드를 사용하여 필터링 할 대리자를 제공 할 수 있습니다 . 그러나 @ IainMH에 동의하지만 거대한 목록이 아니라면 너무 걱정하지 않아도됩니다.


답변

C # 3.0을 사용하는 경우 linq를 사용할 수 있습니다

또는 원하는 경우 C # 3 컴파일러에서 제공하는 특수 쿼리 구문을 사용하십시오.

var filteredList = from x in myList
                   where x > 7
                   select x;