Jak usunąć element z tablicy w C #

153

Powiedzmy, że mam tę tablicę,

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

Jak mogę usunąć element za pomocą „nazwy”? powiedzmy numer 4?

Nawet ArrayListnie pomógł usunąć?

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
źródło
Co jeśli masz zduplikowane wartości na liście? Czy chcesz usunąć tylko pierwsze wystąpienie czy wszystkie wystąpienia?
BenAlabaster
tak, nie mam zduplikowanych wartości, jakiś pomysł?
ahmed
ahmed Czy masz na myśli, że nie, czy tak? (nie obrażając twojego angielskiego, tylko prosząc o wyjaśnienie)
Malfist
@Malfist - przepraszam :), chodziło mi o to, że nie obchodzą mnie zduplikowane wartości, bo na pewno nie ma ich w moim przypadku, jeszcze raz dziękuję
ahmed
3
Nie można usuwać elementów z tablic w języku C #, jak widać w tym przykładowym programie . Możesz stworzyć nową tablicę, skopiować tylko niektóre elementy oryginalnej tablicy i przypisać ją z powrotem do oryginalnej zmiennej. To właśnie dzieje się we wszystkich odpowiedziach.
Nicola Musatti,

Odpowiedzi:

340

Jeśli chcesz usunąć wszystkie wystąpienia 4 bez konieczności znajomości indeksu:

LINQ: (.NET Framework 3.5)

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

Non-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();

Jeśli chcesz usunąć tylko pierwszą instancję:

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();

Bez 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();

Edycja: na wypadek, gdybyś jeszcze tego nie rozgryzł, jak zauważył Malfist, musisz skupić się na .NET Framework 3.5, aby przykłady kodu LINQ działały. Jeśli celujesz w 2,0, musisz odwołać się do przykładów innych niż LINQ.

BenAlabaster
źródło
32
int[] numbers = { 1, 3, 4, 9, 2 };
numbers = numbers.Except(new int[]{4}).ToArray();
meetjaydeep
źródło
21

Możesz także przekonwertować swoją tablicę na listę i wywołać usuń na liście. Następnie możesz przekonwertować z powrotem na swoją tablicę.

int[] numbers = {1, 3, 4, 9, 2};
var numbersList = numbers.ToList();
numbersList.Remove(4);
Dave DP
źródło
11

Kod, który jest zapisany w pytaniu, zawiera błąd

Twoja lista zawiera ciągi znaków „1” „3” „4” „9” i „2” (zwróć uwagę na spacje)

Więc IndexOf (4) nic nie znajdzie, ponieważ 4 jest liczbą int, a nawet „tostring” zamieniłoby ją na „4”, a nie „4”, i nic nie zostanie usunięte.

Arraylist to właściwy sposób robienia tego, co chcesz.

DevinB
źródło
List <T> byłoby lepsze niż ArrayList.
Mike Scott
1
Ta odpowiedź zasługuje na więcej głosów. Chociaż całkowicie zgadzam się z @MikeScott, który List<T>byłby lepszy niż ArrayList, wydaje się, że jest to jedyna odpowiedź, która poprawnie identyfikuje problem, który miał OP, kiedy próbował użyć ArrayList do rozwiązania swojego pierwotnego problemu. OP zrozumiał, że nie możesz zmieniać rozmiaru tablic, czego nikt inny nie zauważył, i zamiast tego próbował użyć typu zmieniającego rozmiar, którego nikt inny nie zauważył, a następnie wpadł w inny problem, na który nikt inny się nie wydaje zauważyć.
phoog
5

Odpowiedź Balabaster jest poprawna, jeśli chcesz usunąć wszystkie wystąpienia elementu. Jeśli chcesz usunąć tylko pierwszy, zrób coś takiego:

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
źródło
5

Opublikowałem tutaj swoje rozwiązanie .

To jest sposób na usunięcie elementu tablicy bez kopiowania do innej tablicy - tylko w ramce tej samej instancji tablicy:

    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
źródło
4
Resize faktycznie kopiuje dane do nowej tablicy (chyba że przekazany nowy rozmiar jest długością przekazanej tablicy); nie zmienia rozmiaru przekazanej instancji tablicy. Dlatego jest to parametr odniesienia. Zobacz referenceource.microsoft.com/mscorlib/R/71074deaf111c4e3.html .
phoog
5

Usunięcie z tablicy nie jest proste, ponieważ wtedy musisz poradzić sobie ze zmianą rozmiaru. Jest to jedna z największych zalet używania czegoś takiego jak List<int>a. Zapewnia Remove/ RemoveAtw 2.0 i wiele rozszerzeń LINQ dla 3.0.

Jeśli możesz, refaktoryzuj, aby użyć List<>lub podobnego.

ctacke
źródło
Myślę, że to najlepsze rozwiązanie w tym przypadku.
Bogdan Doicin
3

Jako ogólne rozszerzenie, kompatybilne z 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();
    }
}

Stosowanie:

int[] numbers = {1, 3, 4, 9, 2};
numbers = numbers.RemoveFromArray(4);
Petrucio
źródło
0

Aby usunąć elementy z ciągu znaków na podstawie wartości kluczy słownika. „Kod 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
źródło
0

Możesz to zrobić w ten sposób:

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();        

źródło