una sacar saber posicion numero mayor matriz imprimir hallar encontrar como arreglo c# arrays linq cumulative-sum

sacar - usando LINQ para encontrar la suma acumulativa de una matriz de números en C#



sacar el numero mayor de una matriz (9)

¿Por qué necesita ser LINQ?

var cumulative = new double[probabilities.Length]; for (int i = 0; i < probabilities.Length; i++) cumulative[i] = probabilities[i] + (i == 0 ? 0 : cumulative[i-1]);

Tengo una cadena csv que contiene dobles (por ejemplo, "0.3,0.4,0.3"), y quiero poder generar una doble matriz que contenga la suma acumulada de estos números (por ejemplo, [0.3.0.7,1.0]).

Hasta ahora tengo

double[] probabilities = textBox_f.Text.Split(new char[]{'',''}).Select(s => double.Parse(s)).ToArray();

que da los números como una matriz, pero no la suma acumulada de los números.

¿Hay alguna forma de continuar esta expresión para obtener lo que quiero o necesito usar la iteración para crear una nueva matriz a partir de la matriz que ya tengo?


Aquí hay una forma de hacerlo usando LINQ:

double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 }; var doublesSummed = new List<double>(); Enumerable.Aggregate(doubles, (runningSum, nextFactor) => { double currentSum = runningSum + nextFactor; doublesSummed.Add(currentSum); return currentSum; }); doublesSummed.Dump();

En LINQPad:

  • 4
  • 5,9
  • 10
  • 12.9

Desea utilizar el operador Aggregate , con una List<double> como acumulador de agregación. De esa manera puedes producir una proyección que es en sí misma una secuencia de sumas.

Aquí hay un ejemplo para comenzar:

double[] runningTotal = textBox_f.Text .Split(new char[]{'',''}) .Select(s => double.Parse(s)) .Aggregate((IEnumerable<double>)new List<double>(), (a,i) => a.Concat(new[]{a.LastOrDefault() + i})) .ToArray();


En primer lugar, no creo que sea una buena tarea para Linq. El viejo foreach lo hará mejor. Pero como un rompecabezas está bien.

La primera idea fue usar subconsultas, pero no me gusta, porque es O (n ^ 2). Aquí está mi solución lineal:

double[] probabilities = new double[] { 0.3, 0.4, 0.3}; probabilities .Aggregate( new {sum=Enumerable.Empty<double>(), last = 0.0d}, (a, c) => new { sum = a.sum.Concat(Enumerable.Repeat(a.last+c,1)), last = a.last + c }, a => a.sum );


Esto es en realidad bastante sencillo de generalizar usando el generador. Aquí hay un nuevo método de extensión llamado Accumulate que funciona como una combinación de Select y Aggregate . Devuelve una nueva secuencia aplicando una función binaria a cada elemento en la secuencia y el valor acumulado hasta el momento.

public static class EnumerableHelpers { public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> self, U init, Func<U, T, U> f) { foreach (var x in self) yield return init = f(init, x); } public static IEnumerable<T> Accumulate<T>(this IEnumerable<T> self, Func<T, T, T> f) { return self.Accumulate(default(T), f); } public static IEnumerable<double> PartialSums(this IEnumerable<double> self) { return self.Accumulate((x, y) => x + y); } public static IEnumerable<int> PartialSums(this IEnumerable<int> self) { return self.Accumulate((x, y) => x + y); } }


Hay un momento para la generalidad, y hay un momento para resolver el problema realmente planteado. Este es uno de los últimos tiempos. Si desea crear un método que convierta una secuencia de dobles en una secuencia de sumas parciales, simplemente haga lo siguiente:

public static IEnumerable<double> CumulativeSum(this IEnumerable<double> sequence) { double sum = 0; foreach(var item in sequence) { sum += item; yield return sum; } }

Fácil. Sin perder el tiempo con agregados y consultas complicadas y todo eso. Fácil de entender, fácil de depurar, fácil de usar:

textBox_f.Text .Split(new char[]{'',''}) .Select(s => double.Parse(s)) .CumulativeSum() .ToArray();

Ahora, observo que si esa es la entrada del usuario, double.Parse puede lanzar una excepción; Podría ser una mejor idea hacer algo como:

public static double? MyParseDouble(this string s) { double d; if (double.TryParse(s, out d)) return d; return null; } public static IEnumerable<double?> CumulativeSum(this IEnumerable<double?> sequence) { double? sum = 0; foreach(var item in sequence) { sum += item; yield return sum; } } ... textBox_f.Text .Split(new char[]{'',''}) .Select(s => s.MyParseDouble()) .CumulativeSum() .ToArray();

y ahora no obtiene una excepción si el usuario comete un error de escritura; obtienes nulos


Tuve un requisito similar hace algún tiempo. Básicamente, necesitaba hacer una agregación, pero también necesitaba seleccionar cada valor intermedio. Así que escribí un método de extensión llamado SelectAggregate (probablemente no es el nombre más apropiado, pero no pude encontrar nada mejor entonces) que pueda usarse así:

double[] numbers = new [] { 0.3, 0.4, 0.3 }; double[] cumulativeSums = numbers.SelectAggregate(0.0, (acc, x) => acc + x).ToArray();

Aquí está el código:

public static IEnumerable<TAccumulate> SelectAggregate<TSource, TAccumulate>( this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func) { source.CheckArgumentNull("source"); func.CheckArgumentNull("func"); return source.SelectAggregateIterator(seed, func); } private static IEnumerable<TAccumulate> SelectAggregateIterator<TSource, TAccumulate>( this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func) { TAccumulate previous = seed; foreach (var item in source) { TAccumulate result = func(previous, item); previous = result; yield return result; } }


utilizar RX:

var input=new double[]{ ... } var output = new List<double>(); input.ToObservable().Scan((e, f) => f + e).Subscribe(output.Add);


var input=new double[]{ ... } double sum=0; var output=input .Select(w=>sum+=w);