Home > Software design >  How can the rows of a list be divided into the largest possible parts (according to the row limit) a
How can the rows of a list be divided into the largest possible parts (according to the row limit) a

Time:12-01

RowLimit: 4

Example 1: List with 10 rows The desired result: 4, 3, 3

Example 2: List with 9 rows The desired result: 3, 3, 3

Example 3: List with 8 rows The desired result: 4, 4

Example 4: List with 7 rows The desired result: 4, 3

At the moment I simply divide the rows according to the rows limit

        public List<List<string>> TextWithRowLimit(List<string> TextRows, int RowLimit)
        {
            List<List<string>> list = new List<List<string>>();
            int RowLimitCounter = 1;
            List<string> TextRowPackages = new List<string>();
            for (int row = 0; row < TextRows.Count;   row)
            {
                TextRowPackages.Add($"{TextRows[row]} ");
                if (RowLimitCounter == RowLimit)
                {
                    list.Add(TextRowPackages);
                    RowLimitCounter = 0;
                    TextRowPackages = new List<string>();
                }
                RowLimitCounter  ;
            }
            if(TextRowPackages.Count>0)
                list.Add(TextRowPackages);
            return list;
        }

CodePudding user response:

Probably not the prettiest code, but I think this will work for you.

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

public class Program
{
    public static void Main()
    {
        var initialList = Enumerable.Range(1, 10).Select(i => i.ToString()).ToList();
        var limit = 4;
        var bucketUtility = new BucketUtility();
        var list = bucketUtility.TextWithRowLimit(initialList, limit);
    }
}

public sealed class BucketUtility
{
    public List<List<string>> TextWithRowLimit(List<string> textRows, int rowLimit)
    {
        var totalRowsCount = textRows.Count;
        var remainder = textRows.Count % rowLimit;
        var totalBucketsNeeded = remainder == 0 ? totalRowsCount / rowLimit : (totalRowsCount / rowLimit)   1;
        // calculate how many would fill buckets
        var initialFillCount = totalBucketsNeeded * rowLimit;
        // this can be negative
        var remainingToFill = totalRowsCount - initialFillCount;
        // size the buckets correctly
        var buckets = SizeBuckets(totalBucketsNeeded, rowLimit, remainingToFill);
        // assign text values to buckets
        int skip = 0;
        var result = buckets.Select((bucketSize, i) =>
        {
            var result = textRows.Select(t => t).Skip(skip).Take(bucketSize).ToList();
            skip  = bucketSize;
            return result;
        }).ToList();
        return result;
    }

    private List<int> SizeBuckets(int totalBucketsNeeded, int rowLimit, int remainingToFill)
    {
        var totalBuckets = Enumerable.Range(0, totalBucketsNeeded).ToList();
        var buckets = new List<int>();
        for (int i = 0; i < totalBuckets.Count; i  )
        {
            int bucketSize = rowLimit;
            if (remainingToFill > 0)
            {
                bucketSize  ;
                remainingToFill--;
            }

            if (remainingToFill < 0)
            {
                bucketSize--;
                remainingToFill  ;
            }

            buckets.Add(bucketSize);
        }

        // order them in correct order
        return buckets.OrderByDescending(i => i).ToList();
    }
}

Can run it here https://dotnetfiddle.net/CxdHaO

  • Related