【问题标题】:How can I mix elements from two list and store them is another list using C#?如何混合两个列表中的元素并将它们存储为使用 C# 的另一个列表?
【发布时间】:2014-03-18 23:25:06
【问题描述】:

我基本上有两个列表:list1 和 list2,它们每个都包含位图图像作为元素。

我的问题是如何从两个列表中随机选择位图元素并将它们混合在一起并存储它们是另一个列表“list3”。

List<Bitmap> list1 = new List<Bitmap>();
List<Bitmap> list2 = new List<Bitmap>();

(List3 的元素是 list1 和 list2 随机混合的,两个列表的大小取决于生成的图像数量)

【问题讨论】:

  • 你对随机部分,“混合”部分或添加到list3有问题吗?
  • Randomize a List<T> in C# 的可能重复项
  • 你今天真的要问这个问题吗? :)
  • 更新了问题;)
  • 嗨,BlueM;不是真的不同的问题,顺便说一下你以前的方法对我不起作用:(

标签: c# image list


【解决方案1】:

这个答案的重点是随机交错两个具有最小偏差的列表。

在两个不等长列表之间交错时,使用适当的算法很重要,并且在使用rnd.Next(2) == 0 时会产生很大的偏差。当交错包含 2 个元素的列表和包含 20 个元素的列表时,这种偏差非常很明显 - 较短列表中的元素将聚集在结果的前面附近。虽然这种偏差并不总是很容易看到,但它存在于任何两个长度不等的列表之间,而没有考虑到列表的“权重”。

因此,不使用rnd.Next(2) == 0 来选择源列表,一个公正的实现应该在所有剩余元素之间公平地选择。

if (randInt(remaining(l1) + remaining(l2)) < remaining(l1)) {
   // take from list 1
   // (also implies list 1 has elements; as rand < 0 never matches)
} else {
   // take from list 2
   // (also implies list 2 has elements)
}

实现可能如下所示:

IEnumerable<T> RandomInterleave<T>(IEnumerable<T> a, IEnumerable<T> b) {
    var rnd = new Random();
    int aRem = a.Count();
    int bRem = b.Count();
    while (aRem > 0 || bRem > 0) {
        var i = rnd.Next(aRem + bRem);
        if (i < aRem) {
            yield return a.First();
            a = a.Skip(1);
            aRem--;
        } else {
            yield return b.First();
            b = b.Skip(1);
            bRem--;
        }
    }
}

var list3 = RandomInterleave(list1, list2).ToList();

【讨论】:

  • +1 用于根据列表长度调整选择偏差并保持结果有序。
  • user2864740;您能否为您的代码提供一些评论以更好地理解这些行;)谢谢
  • “yield return a.First(); a = a.Skip(1);”是什么意思?是什么意思?
  • @user3384676 a.First() 是该输入可枚举中的第一个元素(yield 返回是因为此函数是一个 IEnumerable“生成器”)并且 a = a.Skip(1) 已经超过了 [first] 元素选择输出。
【解决方案2】:

再一次,给你一个例子。

List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
List<int> list3 = new List<int>();

// putting some values into the lists to mix them
for (int i=0; i<50; i++) list1.Add(1);
for (int i=0; i<40; i++) list2.Add(2); 

var rnd = new Random();
int listIndex1 = 0;
int listIndex2 = 0;
while (listIndex1 < list1.Count || listIndex2 < list2.Count) 
{
    if (rnd.Next(2) == 0 || listIndex2 >= list2.Count) 
    {
        list3.Add(list1[listIndex1++]);
    } 
    else 
    {
        list3.Add(list2[listIndex2++]);
    }
}

foreach (var mixed in list3) { Console.WriteLine(mixed); }

输出:

1
1
2
2
2
2
1
2
2
1
1
2
2
2
1
...

【讨论】:

  • BlueM;一如既往地乐于助人;)
  • 最后一件事,因为我的元素是位图,您能告诉我如何在图片框中显示元素吗?
  • 请参阅我在您的图片框上使用 Invoke 的其他答案。如果您想在该 picbox 中重放带有图像的 list3。
  • 我不得不投反对票,因为这种随机化技术在不同尺寸列表之间存在*可怕的偏差*。
猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多