0

I basically have two lists: list1 and list2 which each of them contains bitmap images as elements.

My question is how I can select bitmap elements from both list randomly and mix them together and store them is another list “list3”.

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

(List3 has elements which are mixing of list1 and list2 randomly and the size of the two lists are varying depending on the number of produced images)

2 Answers2

1

This answer focuses on Randomly Interleaving two lists with minimal bias.

It is important to use an appropriate algorithm and is a significant bias when using rnd.Next(2) == 0 when interleaving between two unequal-length lists. This bias is very obvious when interleaving a list of 2 elements and a list of 20 elements - the elements in the shorter list will be clustered near the front of the result. While such a bias is not always readily seen, it exists between any two unequal-length lists without taking the "weights" of the lists into account.

Thus, instead of using rnd.Next(2) == 0 to pick the source list, an unbiased implementation should pick fairly between all the remaining elements.

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)
}

An implementation might look like this:

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();
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 1
    +1 for adjusting the selection bias by list length and keeping the result ordered. – BlueM Mar 20 '14 at 11:25
  • user2864740; could you please give some comment for your code to understand the lines better;) thanks – user3384676 Mar 24 '14 at 00:31
  • what does "yield return a.First(); a = a.Skip(1);" means? – user3384676 Mar 24 '14 at 00:31
  • @user3384676 `a.First()` is the first element left in that input enumerable (the yield return is because this function is an IEnumerable "generator") and the `a = a.Skip(1)` advances over the [first] element already chosen for output. – user2864740 Mar 24 '14 at 02:07
0

And again, an example for you.

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); }

Output:

1
1
2
2
2
2
1
2
2
1
1
2
2
2
1
...
BlueM
  • 6,523
  • 1
  • 25
  • 30