Tengo una gran variedad de objetos Foo. ¿Cómo elimino el segundo elemento de la matriz?
Necesito algo similar RemoveAt()
pero para una matriz regular.
Tengo una gran variedad de objetos Foo. ¿Cómo elimino el segundo elemento de la matriz?
Necesito algo similar RemoveAt()
pero para una matriz regular.
Respuestas:
Si no quieres usar la Lista:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Podrías probar este método de extensión que 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);
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 corta y copiar los elementos antiguos a la nueva matriz, excluyendo el elemento que desea eliminar.
Por lo tanto, probablemente sea mejor usar una Lista en lugar de una matriz.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
usando el Enumerable.ToList()
método del System.Linq
espacio de nombres.
Yo uso este método para eliminar un elemento de una matriz de objetos. En mi situación, mis matrices son pequeñas en 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;
}
Solución de una línea LINQ:
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 ( 1
siendo el segundo elemento en la indexación de matriz basada en C # cero).
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" }
.
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);
}
ref
cuando llamas al Resize
método. La longitud de una instancia de matriz es fija e inmutable.
Aquí hay una versión anterior que tengo que funciona en la versión 1.0 del marco .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]);
}
}
No es exactamente la forma de hacerlo, pero si la situación es trivial y usted valora su tiempo, puede intentar esto para los tipos anulables.
Foos[index] = null
y luego verifique si hay entradas nulas en su lógica.
Como de costumbre, llego tarde a la fiesta ...
Me gustaría agregar otra opción a la lista de buenas soluciones ya presentes. =)
Vería esto como una buena oportunidad para Extensiones.
Referencia:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Entonces, definimos alguna clase estática y en ella, nuestro Método.
Después de eso, podemos usar nuestro método extendido willy-nilly. =)
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"
*/
}
}
}
Pruebe el siguiente código:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
o
myArray = myArray.Where(s => (s != "not_this")).ToArray();
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;
}
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;
}
Aquí hay una pequeña colección de métodos auxiliares que produje en base a algunas de las respuestas existentes. Utiliza tanto extensiones como métodos estáticos con parámetros de referencia para la máxima idealidad:
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 al rendimiento, es decente, pero probablemente podría mejorarse. Remove
se basa IndexOf
y se crea una nueva matriz para cada elemento que desea eliminar llamando 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 la matriz original como referencia, por lo que no es necesario asignar el resultado después, ya que eso ya ocurre internamente.
Hubiera definido un Merge
método para fusionar dos matrices; sin embargo, eso ya se puede lograr con el Add
método pasando 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);
Sé que este artículo tiene diez años y, por lo tanto, probablemente esté muerto, pero esto es lo que intentaría hacer:
Use el método IEnumerable.Skip (), que se encuentra en System.Linq . Saltará el elemento seleccionado de la matriz y devolverá otra copia de la matriz que solo contiene todo excepto el objeto seleccionado. Luego repita eso para cada elemento que desee eliminar y luego guárdelo en una variable.
Por ejemplo, si tenemos una matriz llamada "Muestra" (de tipo int []) con 5 números. Queremos eliminar el segundo, así que intenta "Sample.Skip (2);" debería devolver la misma matriz, excepto sin el segundo número.
Primer paso
Necesitas convertir la matriz en una lista, puedes 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 volver a convertir 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 volver a convertirlo en una matriz como se muestra en el código
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
ejemplos de códigos se pueden encontrar en mi blog , sigue el seguimiento.
.ToArray()
y un List<T>
constructor que tiene una secuencia existente ...
System.Collections.ObjectModel.Collection<Foo>
.