List occurrence明智地阅读c#

本文关键字:occurrence List | 更新日期: 2023-09-27 18:16:23

我有class Like this

  public  class RoomDetails
  {
     public int RoomIndexID {get;set;} --(This is No of Rooms)
     public int roomcategoryID {get;set;} -- (This is No of Category that room have)
     public decimal roomPrice{get;set;}
     public string roomCategory{get;set;}
  }

所以我有这样的RoomDetails列表(data)

  • 1, 1200,单人床
  • 1250,双人床
  • 2,2,400,双人床,额外景观
  • 4530年
  • 2日,床面
  • 1530年
  • 3日,床面
  • 3,2,600,三张大床

所以我想按照程序阅读这个列表。

  • 1, 1200,单人床
  • 1250,双人床
  • 1530年
  • 3日,床面

  • 1, 1200,单人床
  • 1250,双人床
  • 3,2,600,三张大床

  • 1, 1200,单人床
  • 2,2,400,双人床,额外景观
  • 1530年
  • 3日,床面

  • 1, 1200,单人床
  • 2,2,400,双人床,额外景观
  • 3,2,600,三张大床

  • 1, 1200,单人床
  • 4530年
  • 2日,床面
  • 1530年
  • 3日,床面

  • 1, 1200,单人床
  • 4530年
  • 2日,床面
  • 3,2,600,三张大床

如果你对我的问题有任何问题,请问我。

我的数据列表是这样的

  • 房间A—A1
  • B室—B1、B2、B3
  • C室—C1、C2

(实际上A,B, C表示RoomIndexID 's, A1,B1,B2,B3,C1,C2表示roomcategoryID 's)所以我想这样读。

  • A1, B1, C1
  • A1, B1, C2
  • A1, B2, C1
  • A1, B2, C2
  • A1, B3, C1
  • A1, B3 C2

List occurrence明智地阅读c#

如果你想要"LINQy"的解决方案,它会有点复杂。请注意,这是LINQ到对象,所以如果你有IQueryable(例如从EntityFramework),你需要先调用.ToList()

var total = list.GroupBy(x=>x.RoomIndexID)
    .Select(x=>x.Count())
    .Aggregate(1, (s,d)=>s*d);
var counts = list.GroupBy(x => x.RoomIndexID)
    .ToDictionary(x => x.Key, x => x.Count());
var nums = list.GroupBy(x => x.RoomIndexID)
    .Select(x => x.Select((p, i) => new {i, p}))
    .SelectMany(x => x)
    .ToList();
var result = Enumerable.Range(0, total)
    .Select(x =>
        nums.Where(y => {               
            var c = counts[y.p.RoomIndexID];
            var p = counts
                      .Where(z => z.Key > y.p.RoomIndexID)
                      .Aggregate(1, (s,d)=>s*d.Value);
            return y.i == x/p%c;
        })
        .Select(y => y.p)
    );

此处演示:https://dotnetfiddle.net/udf6VA

要简单得多,就像这样:

var groups = list // your input
    .GroupBy(x => x.RoomIndexID)
    .Select(x => x.ToList())
    .ToList();
var result = groups.Skip(1).Aggregate(
    groups.Take(1),
    (x, y) => x.SelectMany(z => y, (a, b) => a.Concat(new[] { b }).ToList()));

基本上,这个想法是首先GroupBy房间索引,以便您获得相同类型的内部序列,然后在这些序列之间执行交叉连接(SelectMany将很好),最后Aggregate连接结果。这三步就可以了。使用以下命令式样式的示例,所涉及的步骤会更清晰:

var groups = list
    .GroupBy(x => x.RoomIndexID)
    .Select(x => x.ToList());
IEnumerable<IEnumerable<RoomDetails>> result = null;
foreach (var item in groups)
{
    if (result == null)
        result = new[] { item };
    else
        result = result.SelectMany(x => item, (x, y) => x.Concat(new[] { y }));
}

如果我们对Aggregate有一个适当的重载,它将序列中第一项的Func作为种子,那么这个事情可以在一步中完成。

// Say you have:
public static TAccumulate Aggregate<TSource, TAccumulate>(
    this IEnumerable<TSource> source,
    Func<TSource, TAccumulate> seeder,
    Func<TAccumulate, TSource, TAccumulate> func)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));
    if (func == null)
        throw new ArgumentNullException(nameof(func));
    using (IEnumerator<TSource> iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            throw new InvalidOperationException("Empty sequence.");
        TAccumulate result = seeder(iterator.Current);
        while (iterator.MoveNext())
        {
            result = func(result, iterator.Current);
        }
        return result;
    }
}
// Then you could do: 
var result = list
    .GroupBy(x => x.RoomIndexID)
    .Select(x => x.ToList())
    .Aggregate(
        x => Enumerable.Repeat(x, 1),
        (x, y) => x.SelectMany(z => y, (a, b) => a.Concat(new[] { b }).ToList()));

整个事情看起来很复杂,因为框架或语言中缺少了一些部分。理想情况下(我认为在许多函数式语言中也是如此),您应该能够做到:

var result = list
    .GroupBy(x => x.RoomIndexID)
    .Aggregate(x => x.Yield(), (x, y) => x.SelectMany(z => y, (a, b) => a.Append(b)));
相关文章: