【问题标题】:What is the best way to partition a collection into smaller collections [duplicate]将集合划分为较小集合的最佳方法是什么[重复]
【发布时间】:2013-08-13 20:37:06
【问题描述】:

我有一系列汽车对象,我正在像这样查看它们:

 var slide = CreateSlide();
 foreach (var car in carCollection) {
      displayonSlide(car, slide)
 }

我现在意识到我只能在一张幻灯片上放 5 辆车,所以我需要将 carCollection 分解为 5 个集合,然后循环遍历这 5 个(所以我为每个收藏中有 5 辆汽车。

根据一定数量的项目(在本例中为 5 个)进行分桶,将单个集合分解为多个较小集合的最佳方法是什么

显然最后一个集合如果不能整除,则可能有余数。

【问题讨论】:

  • @ByteBlast - 你能详细说明一下你将如何使用 take 来创建不同的集合
  • 最初我认为使用TakeSkip 的组合是最好的解决方案,但后来我改变了主意:-p
  • 类似于stackoverflow.com/questions/419019/… 那里的答案详细介绍了不同实现的性能/内存权衡。

标签: c# collections


【解决方案1】:

我在我的代码中使用了这种扩展方法

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> t, int size)
{
   while (t.Any())
   {
      yield return t.Take(size);
      t = t.Skip(size);
   }
}

【讨论】:

  • 它从输入集合的开头开始反复迭代。
  • 就像@MarcinJuraszek 所说,您会获得无限数量的首页。
【解决方案2】:

使用 LINQ:

    var slides = carCollection
        .Select((car, index) => new { car, index })
        .GroupBy(c => c.index / 5)
        .Select( g=>
        {
            var slide = CreateSlide();
            g.ToList().ForEach(c => displayonSlide(c.car, slide));
            return slide;
        }).ToList();

【讨论】:

    【解决方案3】:

    为了避免分组和数学,

    IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> source, int size)
    {
        var partition = new T[size];
        var count = 0;
    
        foreach(var t in source)
        {
            partition[count] = t;
            count ++;
    
            if (count == size)
            {
                yield return partition;
                var partition = new T[size];
                var count = 0;
            }
        }
    
        if (count > 0)
        {
            return partition.Take(count);
        }
    }
    

    这样你就可以了

    cars.Partition(5).AsParallel().ForAll(pageSet =>
    {
        var slide = CreateSlide();
        foreach(var car in pageSet)
        {
            DisplayOnSlide(car, slide);
        }
    });
    

    【讨论】:

      【解决方案4】:

      如果你的收藏是List,可以使用GetRange()方法:

      var input = new List<int> { 1, 5, 6, 7, 8, 9, 34, 14 };
      var k = 5
      
      var res = Enumerable.Range(0, (input.Count - 1) / k + 1)
                          .Select(i => input.GetRange(i * k, Math.Min(k, input.Count - i * k)))
                          .ToList();
      

      【讨论】:

        猜你喜欢
        • 2018-07-16
        • 1970-01-01
        • 1970-01-01
        • 2021-10-27
        • 2020-11-26
        • 2017-04-05
        • 1970-01-01
        • 1970-01-01
        • 2015-02-19
        相关资源
        最近更新 更多