c# - resueltos - Eliminar elemento de una matriz regular
matriz inversa (13)
Tengo una matriz de objetos Foo. ¿Cómo elimino el segundo elemento de la matriz?
Necesito algo similar a RemoveAt()
pero para una matriz regular.
Aquí hay una pequeña colección de métodos de ayuda que produje en función de algunas de las respuestas existentes. Utiliza tanto extensiones como métodos estáticos con parámetros de referencia para una idealidad máxima:
public static class Arr
{
public static int IndexOf<TElement>(this TElement[] Source, TElement Element)
{
for (var i = 0; i < Source.Length; i++)
{
if (Source[i].Equals(Element))
return i;
}
return -1;
}
public static TElement[] Add<TElement>(ref TElement[] Source, params TElement[] Elements)
{
var OldLength = Source.Length;
Array.Resize(ref Source, OldLength + Elements.Length);
for (int j = 0, Count = Elements.Length; j < Count; j++)
Source[OldLength + j] = Elements[j];
return Source;
}
public static TElement[] New<TElement>(params TElement[] Elements)
{
return Elements ?? new TElement[0];
}
public static void Remove<TElement>(ref TElement[] Source, params TElement[] Elements)
{
foreach (var i in Elements)
RemoveAt(ref Source, Source.IndexOf(i));
}
public static void RemoveAt<TElement>(ref TElement[] Source, int Index)
{
var Result = new TElement[Source.Length - 1];
if (Index > 0)
Array.Copy(Source, 0, Result, 0, Index);
if (Index < Source.Length - 1)
Array.Copy(Source, Index + 1, Result, Index, Source.Length - Index - 1);
Source = Result;
}
}
En cuanto a rendimiento, es decente, pero probablemente podría mejorarse. Remove
basa en IndexOf
y se crea una nueva matriz para cada elemento que desea eliminar llamando a RemoveAt
.
IndexOf
es el único método de extensión, ya que no necesita devolver la matriz original. New
acepta múltiples elementos de algún tipo para producir una nueva matriz de dicho tipo. Todos los demás métodos deben aceptar el conjunto original como referencia, de modo que no sea necesario asignar el resultado después, como ocurre internamente.
Hubiera definido un método Merge
para fusionar dos matrices; sin embargo, eso ya se puede lograr con el método Add
al pasar una matriz real frente a múltiples elementos individuales. Por lo tanto, Add
se puede usar de las dos formas siguientes para unir dos conjuntos de elementos:
Arr.Add<string>(ref myArray, "A", "B", "C");
O
Arr.Add<string>(ref myArray, anotherArray);
Aquí hay una versión anterior que tengo que funciona en la versión 1.0 del framework .NET y no necesita tipos genéricos.
public static Array RemoveAt(Array source, int index)
{
if (source == null)
throw new ArgumentNullException("source");
if (0 > index || index >= source.Length)
throw new ArgumentOutOfRangeException("index", index, "index is outside the bounds of source array");
Array dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length - 1);
Array.Copy(source, 0, dest, 0, index);
Array.Copy(source, index + 1, dest, index, source.Length - index - 1);
return dest;
}
Esto se usa así:
class Program
{
static void Main(string[] args)
{
string[] x = new string[20];
for (int i = 0; i < x.Length; i++)
x[i] = (i+1).ToString();
string[] y = (string[])MyArrayFunctions.RemoveAt(x, 3);
for (int i = 0; i < y.Length; i++)
Console.WriteLine(y[i]);
}
}
Así es como lo hice ...
public static ElementDefinitionImpl[] RemoveElementDefAt(
ElementDefinition[] oldList,
int removeIndex
)
{
ElementDefinitionImpl[] newElementDefList = new ElementDefinitionImpl[ oldList.Length - 1 ];
int offset = 0;
for ( int index = 0; index < oldList.Length; index++ )
{
ElementDefinitionImpl elementDef = oldList[ index ] as ElementDefinitionImpl;
if ( index == removeIndex )
{
// This is the one we want to remove, so we won''t copy it. But
// every subsequent elementDef will by shifted down by one.
offset = -1;
}
else
{
newElementDefList[ index + offset ] = elementDef;
}
}
return newElementDefList;
}
Como de costumbre, llego tarde a la fiesta ...
Me gustaría agregar otra opción a la lista de soluciones bonitas ya presente. =)
Me gustaría ver esto como una buena oportunidad para Extensions.
Referencia: http://msdn.microsoft.com/en-us/library/bb311042.aspx
Entonces, definimos una clase estática y en ella, nuestro Método.
Después de eso, podemos utilizar nuestro método extendido de cualquier manera. =)
using System;
namespace FunctionTesting {
// The class doesn''t matter, as long as it''s static
public static class SomeRandomClassWhoseNameDoesntMatter {
// Here''s the actual method that extends arrays
public static T[] RemoveAt<T>( this T[] oArray, int idx ) {
T[] nArray = new T[oArray.Length - 1];
for( int i = 0; i < nArray.Length; ++i ) {
nArray[i] = ( i < idx ) ? oArray[i] : oArray[i + 1];
}
return nArray;
}
}
// Sample usage...
class Program {
static void Main( string[] args ) {
string[] myStrArray = { "Zero", "One", "Two", "Three" };
Console.WriteLine( String.Join( " ", myStrArray ) );
myStrArray = myStrArray.RemoveAt( 2 );
Console.WriteLine( String.Join( " ", myStrArray ) );
/* Output
* "Zero One Two Three"
* "Zero One Three"
*/
int[] myIntArray = { 0, 1, 2, 3 };
Console.WriteLine( String.Join( " ", myIntArray ) );
myIntArray = myIntArray.RemoveAt( 2 );
Console.WriteLine( String.Join( " ", myIntArray ) );
/* Output
* "0 1 2 3"
* "0 1 3"
*/
}
}
}
En una matriz normal, debe barajar todas las entradas de la matriz por encima de 2 y luego cambiar su tamaño usando el método de Redimensionar. Es mejor que uses una ArrayList.
Esta es una forma de eliminar un elemento de matriz, a partir de .Net 3.5, sin copiar a otra matriz, utilizando la misma instancia de matriz con Array.Resize<T>
:
public static void RemoveAt<T>(ref T[] arr, int index)
{
for (int a = index; a < arr.Length - 1; a++)
{
// moving elements downwards, to fill the gap at [index]
arr[a] = arr[a + 1];
}
// finally, let''s decrement Array''s size by one
Array.Resize(ref arr, arr.Length - 1);
}
La naturaleza de las matrices es que su longitud es inmutable. No puede agregar ni eliminar ninguno de los elementos de la matriz.
Tendrá que crear una nueva matriz que sea un elemento más corto y copiar los elementos antiguos a la nueva matriz, excluyendo el elemento que desea eliminar.
Entonces, probablemente sea mejor usar una Lista en lugar de una matriz.
No es exactamente la forma de hacerlo, pero si la situación es trivial y usted valora su tiempo, puede probar esto para los tipos que aceptan nulos.
Foos[index] = null
y luego verifica si hay entradas nulas en tu lógica ...
Si no quieres usar List:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Podrías probar este método de extensión que en realidad no he probado:
public static T[] RemoveAt<T>(this T[] source, int index)
{
T[] dest = new T[source.Length - 1];
if( index > 0 )
Array.Copy(source, 0, dest, 0, index);
if( index < source.Length - 1 )
Array.Copy(source, index + 1, dest, index, source.Length - index - 1);
return dest;
}
Y úsalo como:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
Solución LINQ de una línea:
myArray = myArray.Where((source, index) => index != 1).ToArray();
El 1
en ese ejemplo es el índice del elemento a eliminar, en este ejemplo, según la pregunta original, el segundo elemento (siendo 1
el segundo elemento en la indexación de matriz basada en cero de C #).
Un ejemplo más completo:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Después de ejecutar ese fragmento, el valor de myArray
será { "a", "c", "d", "e" }
.
Utilizo este método para eliminar un elemento de una matriz de objetos. En mi situación, mis arreglos son de poca longitud. Entonces, si tiene matrices grandes, es posible que necesite otra solución.
private int[] RemoveIndices(int[] IndicesArray, int RemoveAt)
{
int[] newIndicesArray = new int[IndicesArray.Length - 1];
int i = 0;
int j = 0;
while (i < IndicesArray.Length)
{
if (i != RemoveAt)
{
newIndicesArray[j] = IndicesArray[i];
j++;
}
i++;
}
return newIndicesArray;
}
Primer paso
Necesita convertir la matriz en una lista, puede escribir un método de extensión como este
// Convert An array of string to a list of string
public static List<string> ConnvertArrayToList(this string [] array) {
// DECLARE a list of string and add all element of the array into it
List<string> myList = new List<string>();
foreach( string s in array){
myList.Add(s);
}
return myList;
}
Segundo paso
Escriba un método de extensión para convertir de nuevo la lista en una matriz
// convert a list of string to an array
public static string[] ConvertListToArray(this List<string> list) {
string[] array = new string[list.Capacity];
array = list.Select(i => i.ToString()).ToArray();
return array;
}
Últimos pasos
Escriba su método final, pero recuerde eliminar el elemento en el índice antes de convertir de nuevo a una matriz como el código show
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
ejemplos de códigos que se pueden encontrar en mi blog , seguir el seguimiento.
private int[] removeFromArray(int[] array, int id)
{
int difference = 0, currentValue=0;
//get new Array length
for (int i=0; i<array.Length; i++)
{
if (array[i]==id)
{
difference += 1;
}
}
//create new array
int[] newArray = new int[array.Length-difference];
for (int i = 0; i < array.Length; i++ )
{
if (array[i] != id)
{
newArray[currentValue] = array[i];
currentValue += 1;
}
}
return newArray;
}