簡體   English   中英

LINQ 其中列表中的列表包含一個值

[英]LINQ where list within a list contains a value

早上好。 我對使用 LINQ 還是很陌生,我已經嘗試了所有我能想到的組合但都沒有成功,我有一個日歷 object 和 object。 CalendarDays 列表。 顯然,我要做的是檢索特定的日期或日期范圍。 我想要日歷值以及 CalendarDay 列表的元素,我嘗試了許多不同的組合。 但他們告訴我我不能將我的 CalendarDay 轉換為 bool 類型,這是我試過的一個例子,但我只得到 CalendarDay。 不是日歷? 不可能同時獲得這兩個值嗎?


        var row = calendar.SelectMany(c => c.Days)
                            .Where(d => d.Date == request.Date);


這是我的日歷 class:

  public class Calendar : ICalendar<string>
    {
        private List<CalendarDay> _calendarDays;

        public Calendar()
        {
            _calendarDays = new List<CalendarDay>();
        }

        public string Id { get; set; }
        public int Year { get; set; }
        public List<CalendarDay> Days { get => _calendarDays; }

        public void AddCalendarDay(int quarter, string season, int period, int weekOfPeriod, int weekOfYear, int dayOfYear, string date)
        {
            var existingDay = _calendarDays.SingleOrDefault(x => x.Date == date);

            if (existingDay == null)
            {
                _calendarDays.Add(new CalendarDay
                {
                    Quarter = quarter,
                    Season = season,
                    Period = period,
                    WeekOfPeriod = weekOfPeriod,
                    WeekOfYear = weekOfYear,
                    DayOfYear = dayOfYear,
                    Date = date
                });
            }
            else
            {
                existingDay.Quarter = quarter;
                existingDay.Season = season;
                existingDay.Period = period;
                existingDay.WeekOfPeriod = weekOfPeriod;
                existingDay.WeekOfYear = weekOfYear;
                existingDay.DayOfYear = dayOfYear;
                existingDay.Date = date;
            }
        }
    }

我忘了提到這是 API 的 GET 方法,此檢索位於 GetByDate 處理程序中。 正如您在下面看到的,GetItemsAsync 的結果被填充到一個列表中。 在那之后,我想提取單個日期並將其傳遞給映射器。 希望這有助於澄清我在尋找什么!

public async Task<CalendarDto> HandleAsync(GetCalendarByDateQuery request)
{
    var spec = new CalendarByYearSpecification(request.Year);
    var result = await _masterRepository.GetItemsAsync(spec);
    
    var calendar = result.Results.ToList();

    // retrieval of the specific date goes here

    var dto = _mapper.Map<Calendar, CalendarDto>(calendar.FirstOrDefault());
    return dto;
}

謝謝!

也許最好的做法是在日歷 class 中創建一個新方法,用於過濾您的日期並返回一個新的日歷 object,其中僅包含所選日期

public class Calendar : ICalendar<string>
{
    private List<CalendarDay> _calendarDays;

    public Calendar()
    {
        _calendarDays = new List<CalendarDay>();
    }

    public Calendar FilterByDate(CalendarDay requestedDate)
    {
         Calendar result = new Calendar();

         // These lines could be a lot more complex if you have many 
         // properties to duplicate. As it stands now this will suffice, 
         // but in more complex cases you could look at some form of 
         // serialization and deserialization 
         result.Id = this.Id;
         result.Year = this.Year;
         result.Days = this.Days.Where(x => x.Date == requestedDate.Date).ToList();
         return result;
    }

現在您需要從日歷 class 的內部代碼訪問 Days 屬性,以便能夠使用 Where 的結果進行設置

 public List<CalendarDay> Days { get => _calendarDays; internal set {_calendarDays = value;}}

這將允許您以這種方式調用該方法

 Calendar filtered = currentCalendar.FilterByDate(aCalendarDayInstance);

聽起來您的日歷 object 已經有了,因此您已經可以使用這些值。 然后,如果您想獲得一個特定的日歷日,那么您可以使用FirstOrDefault獲得它(假設您希望它返回null如果它不存在):

var calendarDay = calendar.Days.FirstOrDefault(d => d.Date == request.Date);

如果你想要一個日期范圍,那么你可以使用Where方法。

var calendarDays = calendar.Days.Where(d => d.Date > request.StartDate && d.Date < request.EndDate).ToList();

希望這可以幫助

這是使用 .Select() 和匿名類型的方法。 首先,您在日歷集合上運行 select 語句,並獲得一個匿名類型,其中包含對日歷的引用以及與您的過濾器匹配的日期集合。 然后你 select 只有 Days.Count 大於零的對象:

var rows = calendar.Select(c => new { Calendar = c, 
                                      Days = c.Days.Where(d => d.Date == request.Date).ToList() })
                   .Where(cd => cd.Days.Count() > 0)
                   .ToList();

foreach (var row in rows)
{
    var cal = row.Calendar;
    foreach (var day in row.Days)
    {
        var dayDate = day.Date;
    }
}

以下是您的代碼的修改版本,其中包含一組使其工作的修復:

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

interface ICalendar<T> : IEnumerable<T>
{
  
}

public class CalendarDay
{
    public int Quarter {get;set;}
    public string Season {get;set;}
    public int Period {get;set;}
    public int WeekOfPeriod {get;set;}
    public int WeekOfYear {get;set;}
    public int DayOfYear {get;set;}
    public string Date {get;set;}
}

public class Calendar : ICalendar<CalendarDay>
{
    private List<CalendarDay> _calendarDays;

    public Calendar()
    {
        _calendarDays = new List<CalendarDay>();
    }

    public string Id { get; set; }
    public int Year { get; set; }
    public List<CalendarDay> Days { get => _calendarDays; }

    IEnumerator IEnumerable.GetEnumerator()
    {
       return _calendarDays.Select(x => x).GetEnumerator();
    }

    public IEnumerator<CalendarDay> GetEnumerator()
    {
       return _calendarDays.Select(x => x).GetEnumerator();
    }

    public void AddCalendarDay(int quarter, string season, int period, int weekOfPeriod, int weekOfYear, int dayOfYear, string date)
    {
        var existingDay = _calendarDays.SingleOrDefault(x => x.Date == date);

        if (existingDay == null)
        {
            _calendarDays.Add(new CalendarDay
            {
                Quarter = quarter,
                Season = season,
                Period = period,
                WeekOfPeriod = weekOfPeriod,
                WeekOfYear = weekOfYear,
                DayOfYear = dayOfYear,
                Date = date
            });
        }
        else
        {
            existingDay.Quarter = quarter;
            existingDay.Season = season;
            existingDay.Period = period;
            existingDay.WeekOfPeriod = weekOfPeriod;
            existingDay.WeekOfYear = weekOfYear;
            existingDay.DayOfYear = dayOfYear;
            existingDay.Date = date;
        }
    }
}

public class Test
{
    public static void Main(string[] args)
    {
        var cal = new Calendar();
        
        var row = cal.Select(c => c.Date).Where(d => d == "Fill Date for Comparison");
    }
}

重要修改:

  1. 使ICalendar<T>實現IEnumerable<T> ,以確保 Linq 調用有效
  2. 您可以直接實現IEnumerable<T>直到並且除非ICalendar<T>實現了某些特殊功能
  3. 我們實現GetEnumerator()方法來編譯代碼
  4. 現在在 class Test中,我們撥打電話, Select結果為IEnumerable<CalendarDay> ,其中Where用於獲取Date並與請求日期進行比較

其他要點

  1. 您應提供簡單/可編譯的代碼,並且只關注主要問題陳述,在這里我必須努力使您的代碼編譯。

  2. SelectMany是Collection flattening, Select是簡單的Collection 選擇,您需要提供直接在其上工作的代碼,無需任何額外要求

  3. 所有 Linq 方法都是擴展方法,您應該從.Net 參考源代碼中查看它們的定義,這將有助於更好地使用代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM