【问题标题】:Use linq to filter by property of subcollection使用 linq 按子集合的属性进行过滤
【发布时间】:2014-03-24 08:40:14
【问题描述】:
class Store
{
    public int ID { get; set; }
    public List<AnnualData> annualData { get; set; }
}

class AnnualData
{
    public int Year { get; set; }
    public Dictionary<string, double> Data { get; set; }
}

我需要获取请求的商店和请求的年份数据。我可以轻松过滤商店:

List<int> storeIDs = new List<int> {12, 13, 14};
List<Store> stores = allData.Stores.Where(s => storeIDs.Contains(s.ID)).ToList();

但我不知道如何按年份列表进一步过滤。

List<int> years = new List<int> {2012, 2013, 2014};
stores = allData.Stores.Where(s => storeIDs.Contains(s.ID)).?????

尝试了 Any/All/Contains,但我显然对 Linq 的理解不够好。提前致谢。

根据 Selmann 和 Timothy 提出的解决方案进行更新 使用您的示例,我仍然在输出中看到商店 1 的所有 3 年 - 我只想在他的案例中看到 2007 年:

   static void Main(string[] args)
    {
        List<Store> allData = new List<Store> {                 
            new Store { ID = 1,
                        annualData = new List<AnnualData> {
                            new AnnualData {
                                Year = 2006,
                                Data = new Dictionary<string, double>{{"Value2006", 1.0}}
                            },
                            new AnnualData {
                                Year = 2007,
                                Data = new Dictionary<string, double>{{"Value2007", 1.1}}
                            },
                            new AnnualData {
                                Year = 2008,
                                Data = new Dictionary<string, double>{{"Value2008", 1.2}}
                            }
                        }
            }
        };

        List<int> storeIDs = new List<int> { 1 };
        List<int> years = new List<int> { 2007 };

        var stores = allData.Where(s => storeIDs.Contains(s.ID) &&
                                     s.annualData.Any(x => years.Contains(x.Year)));

        foreach (Store s in stores)
            foreach (AnnualData a in s.annualData)
                Console.WriteLine(a.Year);

    }

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    你可以使用Any方法:

    stores = allData.Stores.Where(s => storeIDs.Contains(s.ID) && 
                                     s.annualData.Any(x => years.Contains(x.Year)));
    

    【讨论】:

    • 我希望只返回所需的年份。我仍然使用这个解决方案多年。请参阅上面的编辑。
    【解决方案2】:
    stores = allData.Stores
        .Where(s => storeIDs.Contains(s.ID))
        .Select(s => new Store
        {
            ID = s.ID,
            annualData = s.annualData
                .Where(x => years.Contains(x.Year))
                .ToList()
        });
    

    【讨论】:

    • 与 Selmann 的结果相同 - 我得到了所有年份,而不仅仅是我想要的。
    • @Graeme 我已更改答案以匹配您的新规范。这个问题以前不是很清楚。
    • 第二个 where 应该是一个选择。
    • 感谢蒂莫西和蓝先生。这正是我需要的。看起来 contains 和任何以不同的方式做同样的工作?
    • @Graeme enumerable.Contains(item) 在概念上等同于 enumerable.Any(x =&gt; x == item)
    【解决方案3】:

    您不能选择Store 对象,其中AnnualData 对象列表仅包括年份为2007 年的对象,因为不存在此类对象。你得到所有年份的原因是因为你选择了一个 Store 对象,其中列表中的任何 AnnualData 对象都有 2007 年 - 但它仍然返回整个列表。

    要获得一个 Store 列表,其中仅包含您想要的 AnnualData 项目,您需要创建它...

    var stores = allData.Where(s => storeIDs.Contains(s.ID))
                        .Select(s =>
                            new Store { ID = s.ID, annualData = s.annualData.Where(x => years.Any(y => y == x.Year)).ToList() } )
                        .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多