简体   繁体   中英

init float array incrementing index value every x times with Linq

What would be the most effective way to initialize a float array of size n incrementing it every x indices using linq

for instance if array increment is 5 starting on 10 and increment size is 5 array would look like

float[] x = {10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25}

You can argue what is the "best" way. Bit the way how i would do it. At first i would create a helper method that helps you to generate Enumerables.

public static IEnumerable<T> Unfold<T>(T seed, Func<T, T> accumulator) {
    var nextValue = seed;
    while ( true ) {
        yield return nextValue;
        nextValue = accumulator(nextValue);
    }
}

This is a general helper function. For example with

Unfold(1, x => x*2)

it creates you a new IEnumerable where every new number is the double of the previous number. You should use the .Take() or .TakeWhile() methods to limit the amount of generated numbers. If you for example just want the first 10 numbers with power of two

Unfold(1, x => x*2).Take(10).ToList()

You get a List with [1,2,4,8,16,32,64,128,256,512]

Something like Unfold() is in general helpfull to create arbitary Enumerables.

Now to create your list. You wanted to create a list that always add 5. and then every number gets repeated 5 times, and you want reapeat that 4 times. So your first step is

Unfold(10, x => x+5).Take(4)

It will create you an IEnumerable that contains [10, 15, 20, 25] . Now the next step is to repeat every number 5 times.

You can do this with Enumerable.Repeat() . The logic would be.

  1. Go through your list
  2. Create a new Enumerable from every number with Enuerable.Repeat
  3. Flatening every Enumerable to a single Enumerable

That logic above is exactly what SelectMany() does. So the solutions is

var nums = Unfold(10, x => x+5).Take(4).SelectMany(x => Enumerable.Repeat(x, 5));

Now nums is the following list [10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25]

How about this:

var n = 20;
var start = 10;
var step = 5;
var increment = 5;
var x = Enumerable
    .Range(0, n)
    .Select(y => (float)start + increment * (y / step))
    .ToArray();

Note that although I like Linq very much, I must agree with the Robert Harvey that a loop would probably be more legible in this case.

Linq probably isn't your best choice for this problem. That being said, something like this, perhaps?

var groupCount = 4;
var elementsPerGroup = 5;
var increment = 5;

var a = Enumerable
    .Range(0, groupCount)
    .Select(i => Enumerable
                     .Range(0, elementsPerGroup)
                     .Select(r => (float)(10 + increment * i)).ToArray())
    .SelectMany(i => i)
    .ToArray();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM