Сведения о вопросе

rjevskii

10:38, 16th August, 2020

Теги

c#   collections   filtering    

Фильтрация коллекций в C#

Просмотров: 596   Ответов: 9

Я ищу очень быстрый способ отфильтровать коллекцию в C#. в настоящее время я использую универсальные List<object> коллекции, но открыт для использования других структур, если они работают лучше.

В настоящее время я просто создаю новый List<object> и зацикливаюсь на исходном списке. Если критерии фильтрации совпадают, я помещаю копию в новый список.

Есть ли лучший способ сделать это? Есть ли способ фильтровать на месте, чтобы не было необходимости во временном списке?



  Сведения об ответе

+-*/

20:23, 15th August, 2020

Если вы используете 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; в верхней части файла.


  Сведения об ответе

baggs

03:28, 1st August, 2020

Вот блок кода / пример некоторой фильтрации списков с использованием трех различных методов, которые я собрал вместе, чтобы показать фильтрацию списков на основе лямбд и 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


  Сведения об ответе

SSESION

12:30, 25th August, 2020

List имеет метод FindAll, который будет выполнять фильтрацию для вас и возвращать подмножество списка.

msdn имеет отличный пример кода здесь: http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx

EDIT: я написал это до того, как у меня было хорошее понимание метода Linq и Where(). Если бы я написал это сегодня, то, вероятно, использовал бы метод, о котором упоминал Хорхе выше. Однако метод FindAll все еще работает, если вы застряли в среде .NET 2.0.


  Сведения об ответе

VCe znayu

21:58, 4th August, 2020

Вы можете использовать IEnumerable, чтобы устранить необходимость в временном списке.

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

где Совпадения - это имя вашего метода фильтрации. И вы можете использовать это как:

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

Это вызовет функцию GetFilteredItems, когда это необходимо, и в некоторых случаях, когда вы не используете все элементы в отфильтрованной коллекции,это может обеспечить некоторое повышение производительности.


  Сведения об ответе

lool

01:45, 17th August, 2020

Вы можете использовать метод FindAll списка, предоставляя делегат для фильтрации. Хотя я согласен с @ IainMH , что не стоит слишком беспокоиться, если только это не огромный список.


  Сведения об ответе

PHPH

12:50, 8th August, 2020

Использование Linq относительно медленнее, чем использование предиката, поставляемого в метод Lists FindAll. Также нужно быть осторожным с Linq, так как эвмерация списка фактически не выполняется, пока вы не получите доступ к результату. Это может означать, что, когда вы думаете, что создали отфильтрованный список, содержание может отличаться от того, что вы ожидали, когда фактически читали его.


  Сведения об ответе

padenie

02:04, 7th August, 2020

Чтобы сделать это на месте, вы можете использовать метод RemoveAll класса "List<>" вместе с пользовательским "Predicate" class...but все, что нужно сделать, это очистить код... под капотом он делает то же самое, что и вы are...but да, он делает это на месте, поэтому вы делаете то же самое в списке temp.


  Сведения об ответе

SILA

07:47, 3rd August, 2020

Если вы используете C# 3.0, вы можете использовать linq

Или, если вы предпочитаете, используйте специальный синтаксис запроса, предоставленный компилятором C# 3:

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


  Сведения об ответе

SKY

19:18, 26th August, 2020

Если ваш список очень большой и вы фильтруете повторно - вы можете отсортировать исходный список по атрибуту фильтра, двоичный поиск, чтобы найти начальную и конечную точки.

Начальное время O(n*log(n)), затем O (log (n)).

Стандартная фильтрация займет O(n) каждый раз.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться