从几个系列中选择一个元素

时间:2013-06-04 11:17:18

标签: c# algorithm collections

想象一下,您有3个不同项目的列表。您必须通过索引从这些列表中的一个返回项目。索引是从0到Count(<all lists items>)的数字。

示例:

lists 1: 10 items;
lists 2: 5 item;
lists 3: 1 item;

因此,索引应该在0到15之间。按索引项目:

0: lists 1, item 0;
1: lists 2, item 0:
2: lists 3, item 0;
3: lists 1, item 1;
4: lists 2, item 1;
5: lists 1, item 2;
6: lists 2, item 2;
7: lists 1, item 3;
8: lists 2, item 3;
9: lists 1, item 4;
10: lists 2, item 4;
11: lists 1, item 5;
12: lists 1, item 6;
13: lists 1, item 7;
14: lists 1, item 8;
15: lists 1, item 9;

(抱歉有完整的结果。这是我自己的理解检查)。

哪种方式最好:

  • 确定要使用的列表?
  • 从列表中使用哪个索引来获取项目?

可能的解决方案:

  1. 将所有列表中的所有项目放入一个大列表中。大列表中的每个项目都应包含:列表索引;项目(项目的OR索引)从列表中;
  2. 当索引到达时,从大清单返回简单的项目。

3 个答案:

答案 0 :(得分:1)

这是快速解决方案。您可以传递所有列表并获取其枚举器。然后迭代枚举器,同时返回一些结果

public static IEnumerable<T> EnumerateAll<T>(params IEnumerable<T>[] lists)
{
    var enumerators = lists.Select(l => l.GetEnumerator());

    while (enumerators.Any())
    {
        enumerators = enumerators.Where(e => e.MoveNext());

        foreach (var enumerator in enumerators)
            yield return enumerator.Current;           
    }
}

用法:

List<int> list1 = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<int> list2 = new List<int> { 12, 13, 14, 15, 16};
List<int> list3 = new List<int> { 17 };


foreach (int x in EnumerateAll(list1, list2, list3))
    Console.WriteLine(x);

输出

 1 12 17 2 13 3 14 4 15 5 16 6 7 8 9 10

这是更新的解决方案,感谢@Rawling评论

public static IEnumerable<T> EnumerateAll<T>(params IEnumerable<T>[] lists)
{
    var enumerators = lists.Select(l => l.GetEnumerator()).ToList();

    while (enumerators.Any())
    {
        enumerators.RemoveAll(e => !e.MoveNext());

        foreach (var enumerator in enumerators)
            yield return enumerator.Current;
    }
}

还有一个提示 - 如果您需要按索引引用元素,那么只需致电ToList()ToArray()

var items = EnumerateAll(list1, list2, list3).ToList();
var item = items[5];

答案 1 :(得分:1)

无需枚举lists,只需检查index是否小于最小列表数(minCount)乘以列表长度(lists.Length),如果这是case要检索的值非常简单,否则从列表中返回索引,不包括具有最小计数(minLists)的列表,并相应地调整索引:

(当然只有你有一个IList s(或数组)数组才有效

public static T GetByIndex<T>(int index, params IList<T>[] lists){
    var minCount = lists.Min(l => l.Count);
    var minLists = lists.Where(l => l.Count == minCount).ToArray();
    if (index < minCount * lists.Length)
        return lists[index % lists.Length][index / lists.Length];
    else 
        return GetByIndex(index - minCount * minLists.Length, lists.Except(minLists).ToArray());
}

public static void SetByIndex<T>(int index, T val, params IList<T>[] lists){
    var minCount = lists.Min(l => l.Count);
    var minLists = lists.Where(l => l.Count == minCount).ToArray();
    if (index < minCount * lists.Length)
    {
        lists[index % lists.Length][index / lists.Length] = val;
    }
    else 
        SetByIndex(index - minCount * minLists.Length, val, lists.Except(minLists).ToArray());
}

答案 2 :(得分:0)

所以你有N个列表(L0,L1,.. Ln)和项目数量(N0,N1 .. Nn),并且你想在“主索引”K处从这个结构中返回元素。

如果K < N然后从列表编号K返回元素[0](如果你没有空列表lol)。

如果K <= N * Min(N0 ... Nn)则返回由L = K%N值指定的列表中的元素[(K-K%N)/ N](L = 1的L0,L1对于L = 2,L2为L = 0(在您的示例中)。

如果K> N * Min(N0 ... Nn),您可能需要将K短按减去列表的长度减少,并将每个此类列表的N减少1.

类似的东西,可能你需要通过debuggin调整一些值。