0

I want to create same sized smaller arrays from a big array. But items should distribte randomly. I can distribute by order like following:

int[] source = new[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
int i = 0;
int chunkSize = 3;
var result = source.GroupBy(s => i++ / chunkSize).Select(g => g.ToArray()).ToArray();

// [10,20,30][40,50,60][70,80,90]

But result should be random like: // [90,20,50][70,30,60][40,80,10] Can I do it using linq?

barteloma
  • 6,403
  • 14
  • 79
  • 173

4 Answers4

1

The following implements the suggestions in the comments to add an OrderBy clause. There are, of course, other ways to achieve the result, but this is likely the simplest way using LINQ, as requested.

int[] source = new[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
int i = 0;
int chunkSize = 3;
Random r = new Random();
var result = source.OrderBy(x => r.Next()).GroupBy(s => i++ / chunkSize).Select(g => g.ToArray()).ToArray();
mbabramo
  • 2,573
  • 2
  • 20
  • 24
0

You can shuffle any 1D array with this method. If you modify it to return IList<T> instead of void, you can append it into your query:

var result = source.Shuffle().GroupBy(...)
pappbence96
  • 1,164
  • 2
  • 12
  • 20
0

You could do the following.

var arr = new int[] { 1, 1, 2, 6, 6, 7, 1, 1, 0 };
var sizeOfResultArray = 3;
var result  = arr.ChunkBy(sizeOfResultArray);

The extension methods are defined as

public static class Extensions
{

    private static Random rng = new Random();  
    public static IEnumerable<IEnumerable<T>> ChunkBy<T>(this IEnumerable<T> source, int chunkSize) 
    {
        return source.Shuffle()
            .Select((x, i) => new { Index = i, Value = x })
            .GroupBy(x => x.Index / chunkSize)
            .Select(x => x.Select(v => v.Value).ToList())
            .ToList();
    }
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list)  
    {  
        var collection = list.ToList();
        int n = collection.Count();
        while (n > 1) 
        {  
            n--;  
            int k = rng.Next(n + 1);  
            T value = collection[k];  
            collection[k] = collection[n];  
            collection[n] = value;  
        } 
        return collection;
    }
}

The Shuffle is a Fisher-Yates shuffle implementation by Grenade here

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
-1

You need to randomize and then group. Code below should work

            int[] source = new[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
            Random rand = new Random();
            int[] random = source.Select(x => new { num = x, rand = rand.Next() }).OrderBy(x => x.rand).Select(x => x.num).ToArray();
            int groupsize = 3;
            int[][] groups = random.Select((x, i) => new { num = x, index = i })
                .GroupBy(x => x.index / groupsize)
                .Select(x => x.Select(y => y.num).ToArray())
                .ToArray();
jdweng
  • 33,250
  • 2
  • 15
  • 20