matrices - recorrer matriz c#
La forma más eficiente de agregar matrices en C#? (10)
Extraigo datos de un ActiveX de la vieja escuela en forma de matrices de dobles. Inicialmente, no sé la cantidad final de muestras que recuperaré en realidad.
¿Cuál es la forma más eficiente de concatenar estas matrices juntas en C # cuando las saco del sistema?
usando esto podemos agregar dos matrices sin ningún bucle.
Creo que si tiene 2 matrices del mismo tipo que desea combinar en una matriz, hay una manera muy simple de hacerlo.
Aquí está el código:
String[] TextFils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
String[] finalArray = TextFils.Concat(ExcelFils).ToArray();
o
String[] Fils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
Fils = Fils.Concat(ExcelFils).ToArray();
Aquí hay una clase útil basada en lo que dijo Constantin:
class Program
{
static void Main(string[] args)
{
FastConcat<int> i = new FastConcat<int>();
i.Add(new int[] { 0, 1, 2, 3, 4 });
Console.WriteLine(i[0]);
i.Add(new int[] { 5, 6, 7, 8, 9 });
Console.WriteLine(i[4]);
Console.WriteLine("Enumerator:");
foreach (int val in i)
Console.WriteLine(val);
Console.ReadLine();
}
}
class FastConcat<T> : IEnumerable<T>
{
LinkedList<T[]> _items = new LinkedList<T[]>();
int _count;
public int Count
{
get
{
return _count;
}
}
public void Add(T[] items)
{
if (items == null)
return;
if (items.Length == 0)
return;
_items.AddLast(items);
_count += items.Length;
}
private T[] GetItemIndex(int realIndex, out int offset)
{
offset = 0; // Offset that needs to be applied to realIndex.
int currentStart = 0; // Current index start.
foreach (T[] items in _items)
{
currentStart += items.Length;
if (currentStart > realIndex)
return items;
offset = currentStart;
}
return null;
}
public T this[int index]
{
get
{
int offset;
T[] i = GetItemIndex(index, out offset);
return i[index - offset];
}
set
{
int offset;
T[] i = GetItemIndex(index, out offset);
i[index - offset] = value;
}
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
foreach (T[] items in _items)
foreach (T item in items)
yield return item;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
Concatenar matrices es simple usando extensiones linq que vienen de forma estándar con .Net 4
Lo más importante para recordar es que linq funciona con IEnumerable<T>
, por lo que para obtener una matriz como resultado, debe usar el método .ToArray()
al final
Ejemplo de concatenación de dos matrices de bytes:
byte[] firstArray = {2,45,79,33};
byte[] secondArray = {55,4,7,81};
byte[] result = firstArray.Concat(secondArray).ToArray();
Creo que si tienes 2 matrices del mismo tipo que quieres combinar en una tercera matriz, hay una manera muy simple de hacerlo.
aquí está el código:
String[] theHTMLFiles = Directory.GetFiles(basePath, "*.html");
String[] thexmlFiles = Directory.GetFiles(basePath, "*.xml");
List<String> finalList = new List<String>(theHTMLFiles.Concat<string>(thexmlFiles));
String[] finalArray = finalList.ToArray();
Es posible que no necesite concatenar el resultado final en una matriz contigua. En cambio, sigue añadiendo a la lista como lo sugirió Jon. Al final tendrás una matriz dentada (bueno, casi rectangular en realidad). Cuando necesite acceder a un elemento por índice, use el siguiente esquema de indexación:
double x = list[i / sampleSize][i % sampleSize];
La iteración sobre la matriz dentada también es directa:
for (int iRow = 0; iRow < list.Length; ++iRow) {
double[] row = list[iRow];
for (int iCol = 0; iCol < row.Length; ++iCol) {
double x = row[iCol];
}
}
Esto le ahorra asignación de memoria y copia a expensas de un acceso a elementos ligeramente más lento. Si esto será una ganancia de rendimiento neto depende del tamaño de sus datos, patrones de acceso a datos y restricciones de memoria.
La solución parece muy divertida, pero es posible concatenar matrices en solo dos sentencias. Cuando maneja matrices de bytes grandes, supongo que es ineficiente utilizar una lista vinculada para contener cada byte.
Aquí hay un ejemplo de código para leer bytes de una secuencia y extender una matriz de bytes sobre la marcha:
byte[] buf = new byte[8192]; byte[] result = new byte[0]; int count = 0; do { count = resStream.Read(buf, 0, buf.Length); if (count != 0) { Array.Resize(ref result, result.Length + count); Array.Copy(buf, 0, result, result.Length - count, count); } } while (count > 0); // any more data to read? resStream.Close();
La sugerencia de Olmo es muy buena, pero agregaría esto: si no estás seguro del tamaño, es mejor hacerlo un poco más grande que un poco más pequeño. Cuando una lista está llena, tenga en cuenta que duplicará su tamaño para agregar más elementos.
Por ejemplo: supongamos que necesitará alrededor de 50 elementos. Si usa un tamaño de 50 elementos y la cantidad final de elementos es 51, terminará con una lista de 100 tamaños con 49 posiciones desperdiciadas.
Recomiendo la respuesta que se encuentra aquí: ¿cómo concatenar dos matrices en C #?
p.ej
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
Si puede hacer una aproximación del número de elementos que estarán allí al final, use la sobrecarga del constuctor de lista que toma en cuenta como parámetro. Ahorrará algunas costosas duplicaciones de listas. De lo contrario, tienes que pagar por ello.
No se puede agregar a una matriz real: el tamaño de una matriz se fija en el momento de la creación. En su lugar, use una List<T>
que puede crecer según sea necesario.
Alternativamente, mantenga una lista de matrices y concatenelas todas solo cuando haya obtenido todo.
Vea la publicación del blog de Eric Lippert sobre las matrices para obtener más detalles y perspectivas de las que pude proporcionar de manera realista :)