代码之家  ›  专栏  ›  技术社区  ›  Jason Z

在C中筛选集合#

  •  184
  • Jason Z  · 技术社区  · 18 年前

    我正在寻找一种非常快速的方法来过滤C#中的集合。我目前正在使用通用 List<object> 集合,但如果其他结构表现更好,我愿意使用它们。

    目前,我正在创建一个新的 列表<对象> 并循环遍历原始列表。如果筛选条件匹配,我会将副本放入新列表中。

    有更好的方法吗?是否有一种方法可以过滤到位,从而不需要临时列表?

    9 回复  |  直到 4 年前
        1
  •  274
  •   zcoop98    5 年前

    如果你使用的是C#3.0,你可以使用linq,它更好、更优雅:

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

    如果你找不到 .Where ,这意味着您需要导入 using System.Linq; 在文件的顶部。

        2
  •  21
  •   Jon Erickson    12 年前

    这是一个使用三种不同方法进行列表过滤的代码块/示例,我将它们组合在一起,展示了基于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
    
        3
  •  17
  •   d219    7 年前

    List<T> 有a FindAll 该方法将为您进行筛选并返回列表的一个子集。

    MSDN在这里有一个很好的代码示例: http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx

    编辑:我在对LINQ和 Where() 方法。如果我今天写这篇文章,我可能会使用豪尔赫提到的方法。这个 查找全部 如果你陷入困境,这种方法仍然有效。NET 2.0环境。

        4
  •  8
  •   Serhat Ozgel    18 年前

    您可以使用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函数,在某些情况下,如果您没有使用筛选集合中的所有项目,它可能会提供一些良好的性能提升。

        5
  •  4
  •   Adam Haile    18 年前

    要就地执行,您可以使用“List<>”类的RemoveAll方法以及自定义的“Predicate”类。..但所做的只是清理代码。..在引擎盖下,它正在做和你一样的事情。..但是,是的,它确实做到了,所以你也要做同样的临时列表。

        6
  •  4
  •   Community Mohan Dere    9 年前

    您可以使用 FindAll List的方法,提供一个代理来过滤。不过,我同意@ IainMH 除非清单很大,否则不值得过分担心。

        7
  •  3
  •   Tom Lokhorst    18 年前

    如果你使用的是C#3.0,你可以使用linq

    或者,如果你愿意,可以使用C#3编译器提供的特殊查询语法:

    var filteredList = from x in myList
                       where x > 7
                       select x;
    
        8
  •  3
  •   d219    7 年前

    使用LINQ比使用提供给列表的谓词要慢得多 FindAll 方法。还要小心使用LINQ作为枚举 list 在您访问结果之前,它实际上不会执行。这可能意味着,当你认为你已经创建了一个过滤列表时,内容可能与你实际阅读时的预期不同。

        9
  •  1
  •   Daniel Roberts    10 年前

    如果你的列表很大,并且你正在重复过滤,你可以根据过滤器属性对原始列表进行排序,进行二分查找以找到起点和终点。

    初始时间为O(n*log(n)),然后为O(logn)。

    标准过滤每次都需要O(n)。

    推荐文章