Eu tenho uma variedade de objetos Foo. Como faço para remover o segundo elemento da matriz?
Eu preciso de algo semelhante a RemoveAt()
, mas para uma matriz regular.
Eu tenho uma variedade de objetos Foo. Como faço para remover o segundo elemento da matriz?
Eu preciso de algo semelhante a RemoveAt()
, mas para uma matriz regular.
Respostas:
Se você não quiser usar a Lista:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Você pode tentar este método de extensão que eu realmente não testei:
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;
}
E use-o como:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
A natureza das matrizes é que seu comprimento é imutável. Você não pode adicionar ou excluir nenhum dos itens da matriz.
Você precisará criar uma nova matriz com um elemento mais curto e copiar os itens antigos para a nova matriz, excluindo o elemento que deseja excluir.
Portanto, provavelmente é melhor usar uma lista em vez de uma matriz.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
usando o Enumerable.ToList()
método no System.Linq
espaço para nome.
Eu uso esse método para remover um elemento de uma matriz de objetos. Na minha situação, minhas matrizes são pequenas. Portanto, se você tiver matrizes grandes, poderá precisar de outra solução.
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;
}
Solução de linha única LINQ:
myArray = myArray.Where((source, index) => index != 1).ToArray();
O 1
exemplo nesse exemplo é o índice do elemento a ser removido - neste exemplo, pela pergunta original, o 2º elemento ( 1
sendo o segundo elemento na indexação de matriz baseada em zero em C #).
Um exemplo mais completo:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Depois de executar esse snippet, o valor de myArray
será { "a", "c", "d", "e" }
.
Esta é uma maneira de excluir um elemento da matriz, a partir do .Net 3.5, sem copiar para outra matriz - usando a mesma instância da matriz com 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
quando chama o Resize
método. O comprimento de uma instância de matriz é fixo e imutável.
Aqui está uma versão antiga que funciona na versão 1.0 do .NET framework e não precisa de 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;
}
Isso é usado assim:
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]);
}
}
Não é exatamente o caminho a seguir, mas se a situação for trivial e você valorizar seu tempo, tente isso para tipos anuláveis.
Foos[index] = null
e depois verifique se há entradas nulas na sua lógica.
Como sempre, estou atrasado para a festa ...
Eu gostaria de adicionar outra opção à boa lista de soluções já presente. =)
Eu consideraria isso uma boa oportunidade para extensões.
Referência:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Então, definimos alguma classe estática e nela, nosso método.
Depois disso, podemos usar nosso método estendido, quer ou não. =)
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"
*/
}
}
}
Experimente o código abaixo:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
ou
myArray = myArray.Where(s => (s != "not_this")).ToArray();
Aqui está como eu fiz isso ...
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;
}
Aqui está uma pequena coleção de métodos auxiliares que produzi com base em algumas das respostas existentes. Ele utiliza extensões e métodos estáticos com parâmetros de referência para máxima idealidade:
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;
}
}
Em termos de desempenho, é decente, mas provavelmente poderia ser melhorado. Remove
depende IndexOf
e uma nova matriz é criada para cada elemento que você deseja remover chamando RemoveAt
.
IndexOf
é o único método de extensão, pois não precisa retornar a matriz original. New
aceita vários elementos de algum tipo para produzir uma nova matriz do referido tipo. Todos os outros métodos devem aceitar a matriz original como referência, para que não seja necessário atribuir o resultado posteriormente, pois isso já ocorre internamente.
Eu teria definido um Merge
método para mesclar duas matrizes; no entanto, isso já pode ser realizado com o Add
método passando uma matriz real versus vários elementos individuais. Portanto, Add
pode ser usado das duas maneiras a seguir para unir dois conjuntos de elementos:
Arr.Add<string>(ref myArray, "A", "B", "C");
Ou
Arr.Add<string>(ref myArray, anotherArray);
Eu sei que este artigo tem dez anos e, portanto, provavelmente está morto, mas eis o que eu tentaria fazer:
Use o método IEnumerable.Skip (), encontrado em System.Linq . Ele pulará o elemento selecionado da matriz e retornará outra cópia da matriz que contém apenas tudo, exceto o objeto selecionado. Em seguida, basta repetir isso para cada elemento que você deseja remover e depois salvá-lo em uma variável.
Por exemplo, se tivermos uma matriz denominada "Amostra" (do tipo int []) com 5 números. Queremos remover o segundo, tentando "Sample.Skip (2);" deve retornar a mesma matriz, exceto sem o segundo número.
Primeiro passo:
você precisa converter o array em uma lista, pode escrever um método de extensão 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 passo
Escreva um método de extensão para converter novamente a lista em uma 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 passos
Escreva seu método final, mas lembre-se de remover o elemento no índice antes de converter novamente em uma matriz como o código show
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
exemplos de códigos podem ser encontrados no meu blog , acompanhe.
.ToArray()
e um List<T>
construtor que leva uma seqüência existente ...
System.Collections.ObjectModel.Collection<Foo>
.