【问题标题】:LINQ Query to Filter Items By Criteria From Multiple ListsLINQ 查询按条件从多个列表中过滤项目
【发布时间】:2013-04-14 05:47:19
【问题描述】:

我在概念化一些使用 LINQ 应该相当简单的东西时遇到了麻烦。我有一个要根据子对象的 id 值缩小或过滤的集合。

我的主要收藏包括一个景点列表。这是一个点的样子:

public class Spot
{
    public virtual int? ID { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual string TheGood { get; set; }
    public virtual string TheBad { get; set; }
    public virtual IEnumerable<Season> Seasons { get; set; }
    public virtual IEnumerable<PhotographyType> PhotographyTypes { get; set; }
}

我正在尝试按摄影类型和季节过滤景点列表。我有一个 PhotographyTypes 和 Seasons 的 id 列表,每个都在一个 int[] 数组中。这些列表如下所示:

criteria.PhotographyTypeIds //an int[]
criteria.SeasonIds //an int[]

我想构建一个仅包含具有与上述列表中的子对象 (id) 匹配的 Spot 的集合。此功能的目标是按类型和季节过滤一组摄影点,并仅显示匹配的摄影点。任何建议将不胜感激。

【问题讨论】:

    标签: c# .net linq search


    【解决方案1】:

    感谢大家的建议。我最终解决了这个问题。我确定这不是最好的方法,但它现在正在工作。因为这是一个搜索过滤器,所以有很多条件。

    private List<Spot> FilterSpots(List<Spot> spots, SearchCriteriaModel criteria)
        {
            if (criteria.PhotographyTypeIds != null || criteria.SeasonIds != null)
            {
                List<Spot> filteredSpots = new List<Spot>();
    
                if (criteria.PhotographyTypeIds != null)
                {
                    foreach (int id in criteria.PhotographyTypeIds)
                    {
                        var matchingSpots = spots.Where(x => x.PhotographyTypes.Any(p => p.ID == id));
                        filteredSpots.AddRange(matchingSpots.ToList());
                    }
                }
    
                if (criteria.SeasonIds != null)
                {
                    foreach (int id in criteria.SeasonIds)
                    {
                        if (filteredSpots.Count() > 0)
                        {
                            filteredSpots = filteredSpots.Where(x => x.Seasons.Any(p => p.ID == id)).ToList();
                        }
                        else
                        {
                            var matchingSpots = spots.Where(x => x.Seasons.Any(p => p.ID == id));
                            filteredSpots.AddRange(matchingSpots.ToList());
                        }
                    }
                }
                return filteredSpots;
            }
            else
            {
                return spots;
            }
        }
    

    【讨论】:

      【解决方案2】:

      您有一个 ID 数组,其中包含一个 Contains 扩展方法,当 ID 在列表中时,该方法将返回 true。结合 LINQ Where 你会得到:

      List<Spot> spots;   // List of spots
      int[] seasonIDs;    // List of season IDs
      
      var seasonSpots = from s in spots
                        where s.ID != null
                        where seasonIDs.Contains((int)s.ID)
                        select s;
      

      如果需要,您可以将返回的IEnumerable&lt;Spot&gt; 转换为列表:

      var seasonSpotsList = seasonSpots.ToList();
      

      【讨论】:

        【解决方案3】:

        这可能会对您有所帮助:

        List<Spot> spots = new List<Spot>();
        Spot s1 = new Spot();
        s1.Seasons = new List<Season>() 
                     { new Season() { ID = 1 }, 
                       new Season() { ID = 2 }, 
                       new Season() { ID = 3 } 
                     };
        s1.PhotographyTypes = new List<PhotographyType>() 
                     { new PhotographyType() { ID = 1 }, 
                       new PhotographyType() { ID = 2 } 
                     };
        
        Spot s2 = new Spot();
        s2.Seasons = new List<Season>() 
                     { new Season() { ID = 3 }, 
                       new Season() { ID = 4 }, 
                       new Season() { ID = 5 } 
                     };
        s2.PhotographyTypes = new List<PhotographyType>() 
                     { new PhotographyType() { ID = 2 }, 
                       new PhotographyType() { ID = 3 } 
                     };
        
        List<int> PhotographyTypeIds = new List<int>() { 1, 2};
        List<int> SeasonIds = new List<int>() { 1, 2, 3, 4 };
        
        spots.Add(s1);
        spots.Add(s2);
        

        然后:

        var result = spots
                     .Where(input => input.Seasons.All
                                   (i => SeasonIds.Contains(i.ID)) 
                            && input.PhotographyTypes.All
                                   (j =>  PhotographyTypeIds.Contains(j.ID))
                            ).ToList();
        // it will return 1 value 
        

        假设:

        public class Season
        {
            public int ID { get; set; }
            //some codes
        }
        public class PhotographyType
        {
            public int ID { get; set; }
            //some codes
        }
        

        【讨论】:

        • 在将 int[] 转换为 List(因此可以使用 .Contains())并尝试后,它每次都没有返回任何内容。
        • @DonFitz 如果它不能解决您的问题,请告诉我,以便我删除我的答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-15
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多