リストの内部順序を維持する、シャッフルされたマージ済みリストを生成したいと考えています。
例えば:
リストA: 11 22 33
リスト B: 6 7 8
有効な結果: 11 22 6 33 7 8
無効な結果: 22 11 7 6 33 8
リストをランダムに選択し (たとえば、0 から 1 の間の乱数を生成し、0.5 未満の場合はリスト A、それ以外の場合はリスト B)、そのリストから要素を取得して新しいリストに追加します。各リストに要素がなくなるまで繰り返します。
A.Length
区間 [0, ) のランダムな整数を生成しますB.Length
。乱数を並べ替えてから、 の位置にi
を0..A.Length
追加することを繰り返します。これは、から値を挿入するときに、元の値を右にシフトしているためです。A[i]
r[i]+i
B
+i
B
A
これは RNG と同じくらいランダムになります。
元の回答:
static IEnumerable<T> MergeShuffle<T>(IEnumerable<T> lista, IEnumerable<T> listb)
{
var first = lista.GetEnumerator();
var second = listb.GetEnumerator();
var rand = new Random();
bool exhaustedA = false;
bool exhaustedB = false;
while (!(exhaustedA && exhaustedB))
{
bool found = false;
if (!exhaustedB && (exhaustedA || rand.Next(0, 2) == 0))
{
exhaustedB = !(found = second.MoveNext());
if (found)
yield return second.Current;
}
if (!found && !exhaustedA)
{
exhaustedA = !(found = first.MoveNext());
if (found)
yield return first.Current;
}
}
}
marcogの回答に基づく2番目の回答
static IEnumerable<T> MergeShuffle<T>(IEnumerable<T> lista, IEnumerable<T> listb)
{
int total = lista.Count() + listb.Count();
var random = new Random();
var indexes = Enumerable.Range(0, total-1)
.OrderBy(_=>random.NextDouble())
.Take(lista.Count())
.OrderBy(x=>x)
.ToList();
var first = lista.GetEnumerator();
var second = listb.GetEnumerator();
for (int i = 0; i < total; i++)
if (indexes.Contains(i))
{
first.MoveNext();
yield return first.Current;
}
else
{
second.MoveNext();
yield return second.Current;
}
}