Como excluir um elemento de uma matriz em C #

153

Digamos que eu tenho essa matriz,

int[] numbers = {1, 3, 4, 9, 2};

Como posso excluir um elemento por "nome"? , digamos o número 4?

Mesmo ArrayListnão ajudou a excluir?

string strNumbers = " 1, 3, 4, 9, 2";
ArrayList numbers = new ArrayList(strNumbers.Split(new char[] { ',' }));
numbers.RemoveAt(numbers.IndexOf(4));
foreach (var n in numbers)
{
    Response.Write(n);
}
ahmed
fonte
E se você tiver valores duplicados na sua lista? Deseja apenas remover a primeira instância ou todas as instâncias?
BenAlabaster
sim, não tenho valores duplicados, alguma ideia?
ahmed
ahmed Você quer dizer, não, não ou sim? (não insultar o seu Inglês, apenas pedindo esclarecimentos)
Malfist
@ Malfist - desculpe :), eu quis dizer que não me importo com valores duplicados porque tenho certeza de que não há nenhum deles no meu caso, obrigado novamente
ahmed
3
Você não pode remover itens de matrizes em C #, como pode ver neste programa de exemplo . O que você pode fazer é criar uma nova matriz, copiar apenas alguns dos elementos da matriz original e atribuí-la de volta à variável original. Isto é o que é feito em todas as respostas.
Nicola Musatti

Respostas:

340

Se você deseja remover todas as instâncias de 4 sem precisar conhecer o índice:

LINQ: (.NET Framework 3.5)

int[] numbers = { 1, 3, 4, 9, 2 };
int numToRemove = 4;
numbers = numbers.Where(val => val != numToRemove).ToArray();

Não LINQ: (.NET Framework 2.0)

static bool isNotFour(int n)
{
    return n != 4;
}

int[] numbers = { 1, 3, 4, 9, 2 };
numbers = Array.FindAll(numbers, isNotFour).ToArray();

Se você deseja remover apenas a primeira instância:

LINQ: (.NET Framework 3.5)

int[] numbers = { 1, 3, 4, 9, 2, 4 };
int numToRemove = 4;
int numIndex = Array.IndexOf(numbers, numToRemove);
numbers = numbers.Where((val, idx) => idx != numIndex).ToArray();

Não LINQ: (.NET Framework 2.0)

int[] numbers = { 1, 3, 4, 9, 2, 4 };
int numToRemove = 4;
int numIdx = Array.IndexOf(numbers, numToRemove);
List<int> tmp = new List<int>(numbers);
tmp.RemoveAt(numIdx);
numbers = tmp.ToArray();

Edit: Apenas no caso de você ainda não ter descoberto, como Malfist apontou, você precisa ter como alvo o .NET Framework 3.5 para que os exemplos de código LINQ funcionem. Se você estiver direcionando para a 2.0, precisará fazer referência aos exemplos que não são do LINQ.

BenAlabaster
fonte
32
int[] numbers = { 1, 3, 4, 9, 2 };
numbers = numbers.Except(new int[]{4}).ToArray();
meetjaydeep
fonte
21

Você também pode converter sua matriz em uma lista e chamar remover na lista. Você pode converter novamente para sua matriz.

int[] numbers = {1, 3, 4, 9, 2};
var numbersList = numbers.ToList();
numbersList.Remove(4);
Dave DP
fonte
11

O código que está escrito na pergunta possui um bug

Sua lista de matrizes contém seqüências de caracteres de "1" "3" "4" "9" e "2" (observe os espaços)

Portanto, IndexOf (4) não encontrará nada porque 4 é um int, e até "tostring" o converteria em "4" e não "4", e nada será removido.

Uma lista de matrizes é a maneira correta de fazer o que você deseja.

DevinB
fonte
Lista <T> seria melhor que ArrayList.
Mike Scott
1
Esta resposta merece mais votos. Embora eu concorde absolutamente com o @MikeScott que List<T>seria melhor que o ArrayList, essa parece ser a única resposta que identifica corretamente o problema que o OP teve ao tentar usar o ArrayList para resolver seu problema original. O OP entendeu que você não pode redimensionar matrizes, que ninguém mais parece ter notado, e tentou usar um tipo redimensionável, que ninguém mais parece ter notado, e depois foi atropelado por um problema diferente, que ninguém mais parece ter notado.
Phoog
5

A resposta do Balabaster está correta se você deseja remover todas as instâncias do elemento. Se você deseja remover apenas o primeiro, faça algo assim:

int[] numbers = { 1, 3, 4, 9, 2, 4 };
int numToRemove = 4;
int firstFoundIndex = Array.IndexOf(numbers, numToRemove);
if (numbers >= 0)
{
    numbers = numbers.Take(firstFoundIndex).Concat(numbers.Skip(firstFoundIndex + 1)).ToArray();
}
Vojislav Stojkovic
fonte
5

Postei minha solução aqui .

Esta é uma maneira de excluir um elemento da matriz sem copiar para outra matriz - apenas no quadro da mesma instância da matriz:

    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);
    }
infografnet
fonte
4
Redimensionar na verdade copia os dados para uma nova matriz (a menos que o novo tamanho passado seja o comprimento da matriz passada); isso não altera o tamanho da instância da matriz passada. É por isso que é um parâmetro de referência. Consulte o sourcesource.microsoft.com/mscorlib/R/71074deaf111c4e3.html .
Phoog
5

Remover de uma matriz em si não é simples, pois você precisará lidar com o redimensionamento. Essa é uma das grandes vantagens de usar algo como um List<int>. Ele fornece Remove/ RemoveAtno 2.0 e muitas extensões LINQ para 3.0.

Se você puder, refatorar para usar um List<>ou similar.

ctacke
fonte
Eu acho que é a melhor solução neste caso.
Bogdan Doicin
3

Como uma extensão genérica, compatível com 2.0:

using System.Collections.Generic;
public static class Extensions {
    //=========================================================================
    // Removes all instances of [itemToRemove] from array [original]
    // Returns the new array, without modifying [original] directly
    // .Net2.0-compatible
    public static T[] RemoveFromArray<T> (this T[] original, T itemToRemove) {  
        int numIdx = System.Array.IndexOf(original, itemToRemove);
        if (numIdx == -1) return original;
        List<T> tmp = new List<T>(original);
        tmp.RemoveAt(numIdx);
        return tmp.ToArray();
    }
}

Uso:

int[] numbers = {1, 3, 4, 9, 2};
numbers = numbers.RemoveFromArray(4);
Petrucio
fonte
0

' Para remover itens da cadeia de caracteres com base nos valores de chave do dicionário. Código VB.net

 Dim stringArr As String() = "file1,file2,file3,file4,file5,file6".Split(","c)
 Dim test As Dictionary(Of String, String) = New Dictionary(Of String, String)
 test.Add("file3", "description")
 test.Add("file5", "description")
 stringArr = stringArr.Except(test.Keys).ToArray()
SP007
fonte
0

Você pode fazer desta maneira:

int[] numbers= {1,3,4,9,2};     
List<int> lst_numbers = new List<int>(numbers);
int required_number = 4;
int i = 0;
foreach (int number in lst_numbers)
{              
    if(number == required_number)
    {
        break;
    }
    i++;
}
lst_numbers.RemoveAt(i);
numbers = lst_numbers.ToArray();        

fonte