代码之家  ›  专栏  ›  技术社区  ›  Jon Galloway

通用LINQ函数-以selection func作为参数的selectmany

  •  4
  • Jon Galloway  · 技术社区  · 15 年前

    我有一个有很多字符串数组的类。我想要一个通用函数,它可以使我 List<string> 对于给定的属性。例子:

    public class Zoo 
    {    
      string Name { get; set;}
      string[] Animals { get; set;}
      string[] Zookeepers { get; set;}
      string[] Vendors { get; set;}
    }
    

    我想要一个通用函数,它将使我 列表<字符串> 名单上的动物?我希望这是通用的,所以我也可以得到一个独特的动物园管理员和卖主名单。

    我一直在尝试这个,但它没有编译:

    public static List<string> GetExtendedList(Func<Zoo, string[]> filter)
    {
            var Zoos = QueryZoos(HttpContext.Current);
            return Zoos.Where(z => z.Type == "Active")
                .SelectMany(filter)
                .Distinct()
                .OrderBy(s => s);
        }
    

    注意:这与我以前问过的两个问题有关,但合并信息时遇到问题。我以前问过 how to query using SelectMany (SO 1229897) 分别询问如何编写一个通用函数 gets a list using Select rather than SelectMany (SO 1278989) .

    3 回复  |  直到 15 年前
        1
  •  19
  •   Amy B    15 年前

    “每个动物园”

    点击

    假设你有动物园的名单:

    List<Zoo> zooList = GetZooList();
    

    然后,如果您想要不同于所有动物园的动物,您可以这样应用selectmany:

    List<string> animalList = zooList
      .SelectMany(zoo => zoo.animals)
      .Distinct()
      .ToList();
    

    如果您通常执行此任务并希望一个函数包装这三个调用,那么您可以这样编写一个函数:

    public static List<string> GetDistinctStringList<T>(
      this IEnumerable<T> source,
      Func<T, IEnumerable<string>> childCollectionFunc
    )
    {
      return source.SelectMany(childCollectionFunc).Distinct().ToList();
    }
    

    这将被称为:

    List<string> animals = ZooList.GetDistinctStringList(zoo => zoo.animals);
    

    对于不编译的代码示例(您没有给出任何错误消息),我推断您需要添加tolist():

    .OrderBy(s => s).ToList();
    

    另一个问题(无法推断类型参数的原因)是 string[] 不执行 IEnumerable<string> .将该类型参数更改为 IEnumerable<字符串> 而不是 字符串[ ]

        2
  •  1
  •   Andrew Hare    15 年前

    最好的方法是创建一个 HashSet<String> 对于每一个 String[] -这将过滤掉所有重复项。

    自从 HashSet<T> 具有接受 IEnumerable<T> 您可以简单地实例化 哈希集<t> 通过将每个数组传递给构造函数。结果 哈希集<t> 将是 Strings . 虽然这不是一个 List<String> 如你所要求的, 哈希集<t> 实施 ICollection<T> 你需要的很多方法可能都是可用的。

    static ICollection<String> GetDistinct(IEnumerable<String> sequence)
    {
        return new HashSet<String>(sequence);
    }
    
        3
  •  1
  •   Tim Jarvis    15 年前

    也许我错过了你的意思,但简单地说…

    List<String> distinctAnimals = zoo.Animals.Distinct().ToList();
    

    会按你的要求去做吗,我想你是说别的什么?

    编辑: 如果您有一个动物园的列表,但是想要不同的动物,那么选择多个是正确的使用方法,我觉得使用LINQ声明性语法更容易…

    List<String> animals = (from z in zoos
                           from s in z.Animals
                           select s).Distinct().ToList();