Me pregunto si existe una funcionalidad .NET incorporada para cambiar cada valor en una matriz en función del resultado de un delegado proporcionado. Por ejemplo, si tuviera una matriz {1,2,3}
y un delegado que devuelve el cuadrado de cada valor, me gustaría poder ejecutar un método que tome la matriz y delegar, y devuelva {1,4,9}
. ¿Ya existe algo como esto?C#: Alteración de valores para cada elemento en una matriz
Respuesta
No es que esté al tanto de (reemplazando cada elemento en lugar de convertir a un nuevo conjunto o secuencia), pero es muy fácil de escribir:
public static void ConvertInPlace<T>(this IList<T> source, Func<T, T> projection)
{
for (int i = 0; i < source.Count; i++)
{
source[i] = projection(source[i]);
}
}
Uso:
int[] values = { 1, 2, 3 };
values.ConvertInPlace(x => x * x);
De Por supuesto, si realmente no necesita para cambiar la matriz existente, las otras respuestas publicadas usando Select
serían más funcionales. O el ConvertAll
método existente de .NET 2:
int[] values = { 1, 2, 3 };
values = Array.ConvertAll(values, x => x * x);
todo esto es suponiendo una sola dimensional array. Si desea incluir matrices rectangulares, se torna más complicado, especialmente si desea evitar el boxeo.
+1 para ConvertAll que en realidad es lo que el OP solicitó "método que toma el conjunto y delega, y devuelve ..." –
No entiendo por qué esto supera la respuesta de Nathan para la respuesta aceptada. ¿Qué me estoy perdiendo? Select hace exactamente lo que necesita, ¿no? –
@Richard: Es posible que la respuesta de Nathan fuera tan completa cuando se aceptó mi respuesta, en términos del soporte multidimensional. La forma en que leí la pregunta de OP para empezar, pensé que quería modificar la matriz en su lugar, que solo cubre mi respuesta. Para la conversión de matriz a matriz, 'Array.ConvertAll' es más eficiente y no requiere .NET 3.5. Si solo se requiere una secuencia, 'Seleccionar' está bien como se menciona en mi respuesta. –
LINQ proporciona soporte para proyecciones utilizando el método Select extensión:
var numbers = new[] {1, 2, 3};
var squares = numbers.Select(i => i*i).ToArray();
También puede utilizar el poco menos fluidez Array.ConvertAll método:
var squares = Array.ConvertAll(numbers, i => i*i);
matrices dentadas pueden ser procesados por los nidos de las proyecciones:
var numbers = new[] {new[] {1, 2}, new[] {3, 4}};
var squares = numbers.Select(i => i.Select(j => j*j).ToArray()).ToArray();
Las matrices multidimensionales son un poco más complejas. He escrito el siguiente método de extensión que proyecta cada elemento en una matriz multidimensional sin importar su rango.
static Array ConvertAll<TSource, TResult>(this Array source,
Converter<TSource, TResult> projection)
{
if (!typeof (TSource).IsAssignableFrom(source.GetType().GetElementType()))
{
throw new ArgumentException();
}
var dims = Enumerable.Range(0, source.Rank)
.Select(dim => new {lower = source.GetLowerBound(dim),
upper = source.GetUpperBound(dim)});
var result = Array.CreateInstance(typeof (TResult),
dims.Select(dim => 1 + dim.upper - dim.lower).ToArray(),
dims.Select(dim => dim.lower).ToArray());
var indices = dims
.Select(dim => Enumerable.Range(dim.lower, 1 + dim.upper - dim.lower))
.Aggregate(
(IEnumerable<IEnumerable<int>>) null,
(total, current) => total != null
? total.SelectMany(
item => current,
(existing, item) => existing.Concat(new[] {item}))
: current.Select(item => (IEnumerable<int>) new[] {item}))
.Select(index => index.ToArray());
foreach (var index in indices)
{
var value = (TSource) source.GetValue(index);
result.SetValue(projection(value), index);
}
return result;
}
El método anterior se puede probar con una serie de rango 3 de la siguiente manera:
var source = new int[2,3,4];
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
source[i, j, k] = i*100 + j*10 + k;
var result = (int[,,]) source.ConvertAll<int, int>(i => i*i);
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
{
var value = source[i, j, k];
Debug.Assert(result[i, j, k] == value*value);
}
Su ejemplo probablemente debería usar un delegado en lugar de especificar la función en el lambda, para responder la pregunta más específicamente. –
Muy limpio. ¿Esto tomará en cuenta las matrices multidimensionales? – JustOnePixel
Ah, ahí está. Estaba buscando un método de Apply o algo así. Nunca habría pensado en llamarlo Select, pero supongo que eso concuerda con la base LINQ de todos los métodos de extensión divertidos. – jdmichal
Usando System.Linq que podría hacer algo como:
var newArray = arr.Select(x => myMethod(x)).ToArray();
consultas LINQ podría fácilmente resuelva esto para usted - asegúrese de que está haciendo referencia a System.Core.dll y tenga un
using System.Linq;
declaración. Por ejemplo, si usted tenía su matriz en una variable llamada numberArray, el siguiente código sería darle exactamente lo que está buscando:
var squares = numberArray.Select(n => n * n).ToArray();
La llamada final "ToArray" sólo es necesario si realmente necesita una matriz , y no un IEnumerable <int>.
Impresionante, gracias. ¿Esto tomará en cuenta las matrices multidimensionales? – JustOnePixel
No, para eso, desearía una selección anidada, como numberArrays.Select (as => as.Select (n => n * n) .ToArray()). ToArray(). Para un enfoque discutible más legible, simplemente use dos bucles anidados. – Ben
puede usar linq para lograr esto en forma abreviada, pero tenga cuidado, recuerde que de todos modos se produce un foreach debajo.
int[] x = {1,2,3};
x = x.Select((Y) => { return Y * Y; }).ToArray();
Aquí hay otra solución para las matrices M x N, donde M y N no se conocen en tiempo de compilación.
// credit: https://blogs.msdn.microsoft.com/ericlippert/2010/06/28/computing-a-cartesian-product-with-linq/
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
foreach (var sequence in sequences)
{
// got a warning about different compiler behavior
// accessing sequence in a closure
var s = sequence;
result = result.SelectMany(seq => s, (seq, item) => seq.Concat<T>(new[] { item }));
}
return result;
}
public static void ConvertInPlace(this Array array, Func<object, object> projection)
{
if (array == null)
{
return;
}
// build up the range for each dimension
var dimensions = Enumerable.Range(0, array.Rank).Select(r => Enumerable.Range(0, array.GetLength(r)));
// build up a list of all possible indices
var indexes = EnumerableHelper.CartesianProduct(dimensions).ToArray();
foreach (var index in indexes)
{
var currentIndex = index.ToArray();
array.SetValue(projection(array.GetValue(currentIndex)), currentIndex);
}
}
Esa es probablemente la mejor que he encontrado ... y es bueno que le hayas dado el crédito al tipo que la escribió (aunque el tipo que hizo la pregunta se cabreó no la aplicó) –
- 1. Seleccionar cada enésimo elemento de una matriz
- 2. Obtener elemento específico de cada matriz secundaria
- 3. ¿Manera fácil de probar si cada elemento en una matriz numpy se encuentra entre dos valores?
- 4. Matlab, ¿Cómo comparo cada elemento de una matriz de filas con cada elemento de otra matriz de filas?
- 5. ¿Cómo se selecciona cada enésimo elemento en una matriz?
- 6. Aplicar el método para cada elemento en la matriz/enumerables
- 7. Seleccionar/asignar cada elemento de una matriz de Powershell a una nueva matriz
- 8. obtener matriz de claves para cada elemento bajo JSONArray
- 9. Adición de valores a una C# matriz
- 10. ¿Cómo puedo usar Hamcrest para verificar si cada elemento en una matriz de dobles está "cerca" de cada elemento en otra matriz?
- 11. ¿Cómo puedo usar a para cada ciclo en una matriz?
- 12. ¿Cómo creo una matriz en C++ utilizando new e inicializando cada elemento?
- 13. ¿Cómo implemento una matriz de bits en C/Objetivo C
- 14. Matlab: ¿ejecuta una función con parámetros para cada elemento de una matriz?
- 15. Ejecutando "strpos" en cada elemento de la matriz
- 16. C++ función para elegir de una lista donde cada elemento tiene una probabilidad distinta
- 17. ¿Cómo se configuran los valores de una matriz a los valores de otra matriz en Java?
- 18. Impresión de una coma (,) después de cada elemento de una matriz
- 19. imprimir los valores de una matriz (MAT) en OpenCV C++
- 20. Rieles 3: botón de opción para cada elemento de una matriz
- 21. ¿Cómo obtener valores distintos de una matriz en C#?
- 22. sustituir valores en una matriz
- 23. Alteración de la matriz de salida de función numpy en su lugar
- 24. ¿Cómo aplicar una función a cada elemento de una columna de matriz en Postgres?
- 25. Cómo eliminar un elemento de una matriz en C#
- 26. Ruby: prueba cada elemento de la matriz, obtienes un resultado
- 27. Valores flotantes como índice en una matriz en C++
- 28. Javascript cómo mostrar cada elemento de la matriz en una nueva línea
- 29. ¿Existe alguna forma clara de declarar una matriz Java con el mismo valor para cada elemento?
- 30. Insertar varios valores de una matriz en otra matriz
Tradicionalmente, eso se llamaría Mapa; en Linq se llama Seleccionar. –