简体   繁体   中英

Divide List<string> into sublists of equal size N

I'm trying to slice a List of strings (size N) and return a range based on the list being sliced into equal parts (X).

So for instance, if I have a list of say 10 elements, and my number of tiers is 5.

Elements 0 and 1 are tier 1. Elements 2 and 3 are tier 2. At the end of the method I return the tier specified in the params.

What I'm struggling with is if the list count isn't divisible by the number of tiers. For instance, 23 / 5 = 4.6. So that means they'll be 5 sets of 4, and then 3 left over. I'd like the result to be 5 tiers of 5, 5, 5, 5, 3 (with the final tier just the remaining number of elements).

I've included my code so far, but I'm really stuck on how to ensure the list sizes are as equal as possible and how to handle remainders.

// Gets a list and returns a range by the tier specified
public List<string> GetRangeByTierIndex(List<string> listToDivide, int numOfTiers, int tierIndexToGet)
{
    int numOfElementsPerList = listToDivide.Count / numOfTiers;

    int index = (tierToGet - 1) * numOfElementsPerList;

    return listToDivide.GetRange(index, numOfElementsPerList);
}

Note: Forgot to mention, I can't use LINQ for this either (AOT and iOS problems).

The idea is to use modulo which is remainder of division of listToDivide.Count by numOfTiers . If that remainder is greater than zero all tiers which index is less or equal to that remainder will have one more element. Because of that, start index of every tier must be corrected also. Note that I haven't wrote any checks (like if number of elements in main list is zero, numOfTiers < tierIndexToGet , etc... but you can add those checks if you need). Also, this will, for your example, give lists with 5, 5, 5, 4, 4 elements instead of 5, 5, 5, 5, 3 but I think this is even better. Anyway I hope it will be good for your needs. Code should look something like:

public List<string> GetRangeByTierIndex(List<string> listToDivide, int numOfTiers, int tierIndexToGet)
{
    int remaining = listToDivide.Count % numOfTiers;
    int numOfElementsPerList = listToDivide.Count / numOfTiers;
    int index = (tierIndexToGet - 1) * numOfElementsPerList;
    if (remaining > 0)
    {
        // most increase position of index because of numOfElementsPerList correction bellow
        index += tierIndexToGet > remaining ? remaining : tierIndexToGet - 1;
        // first 'remaining-th' tiers will have +1 element
        numOfElementsPerList += tierIndexToGet <= remaining ? 1 : 0;
    }
    return listToDivide.GetRange(index, numOfElementsPerList);
}

Example: 23 and 5.

  • 23/5 = 4 // 4 tiers of 5 - use integer division
  • 23%5 = 3 // 1 tier of 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM