M.kazem Akhgary
M.kazem Akhgary

Reputation: 19149

how to distribute items in number of lists?

Question: How to distribute items in number of lists? following are examples:


var items = new List<object>();
var containers = new List<List<object>>();

int c = -1; // indexer for container.

for(int i = 0; i < items.Count; i++)
{
    // disturbute items to containers

    if (i % (items.Count/containers.Count) == 0) c++; // this is wrong. when to increment?

    containers[c].Add(items[i]);
}

I'm pretty sure only if statement is wrong. Its getting confusing how to handle i.

Upvotes: 0

Views: 716

Answers (3)

Scott Hannen
Scott Hannen

Reputation: 29207

If you want to isolate this behavior into something reusable and testable:

public class ListBalancer
{
    public void BalanceItemsBetweenLists<T>(
        IEnumerable<T> input,
        IEnumerable<IList<T>> targets)
    {
        var inputArray = input as T[] ?? input.ToArray();
        var targetArray = targets as IList<T>[] ?? targets.ToArray();
        var currentTargetIndex = 0;
        foreach (var item in inputArray)
        {
            targetArray[currentTargetIndex].Add(item);
            currentTargetIndex++;
            if (currentTargetIndex == targetArray.Length) currentTargetIndex = 0;
        }
    }
}

[TestClass]
public class ListBalancerTests
{
    [TestMethod]
    public void BalancesListsWhenAddingItems()
    {
        var source = Enumerable.Range(1, 11);
        var targets = Enumerable.Range(1, 8).Select(n => new List<int>()).ToArray();
        new ListBalancer().BalanceItemsBetweenLists(source, targets);

        Assert.AreEqual(2, targets[0].Count);
        Assert.AreEqual(2, targets[1].Count);
        Assert.AreEqual(2, targets[2].Count);
        Assert.AreEqual(1, targets[3].Count);
    }
}

It seems like a little bit of extra work. But you probably found that the process of debugging when it didn't do what was expected took a little extra time, too. It might have been necessary to start a console application or some other app to test the behavior. If you write a class with a unit test you might still have to debug, but it's faster and more self-contained. You finish the one class with the one behavior, test it, and then move on.

Personally I found that once I formed the habit I could write code a little faster and with fewer bugs because I made my debugging process smaller and easier.

Upvotes: 1

ya23
ya23

Reputation: 14496

Think about the algorithm. When inserting item, you insert it to a list and then move to next one. When reaching last list, start inserting back to the first. Code (written in notepad, so may not compile):

var items = new List<object>();
var containers = new List<List<object>>();

int c = 0;

for (int i = 0; i < items.Count; i++)
{
    c++; // move to next container

    // when reached to the end, insert again to first list
    if (c == containers.Count)
    {
        c = 0;
    }
    containers[c].Add(items[i]);
}

This can be made a bit shorter:

var items = new List<object>();
var containers = new List<List<object>>();

int c = 0;
foreach (int item in items)
{
    c = (c == containers.Count - 1) ? 0 : c + 1;
    containers[c].Add(item);
}

Upvotes: 1

mjwills
mjwills

Reputation: 23819

Try this:

    static void Main(string[] args)
    {
        var items = new List<object>() {1, 2, 3, 4, 5, 6};
        var containers = new List<List<object>>() { new List<object>(), new List<object>(),  new List<object>()};

        int c = 0; // indexer for container.
        int containerCount = containers.Count;

        for (int i = 0; i < items.Count; i++, c++)
        {
            c = c % containerCount;
            containers[c].Add(items[i]);
        }
    }

Upvotes: 2

Related Questions