Cách xóa phần tử khỏi một mảng trong C #


153

Hãy nói rằng tôi có mảng này,

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

Làm thế nào tôi có thể xóa một phần tử bằng "tên"? , hãy nói số 4?

Thậm chí ArrayListkhông giúp xóa?

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

Điều gì nếu bạn có các giá trị trùng lặp trong danh sách của bạn? Bạn có muốn xóa phiên bản đầu tiên hoặc tất cả các phiên bản không?
BenAlabaster

có, tôi không có giá trị trùng lặp, bất kỳ ý tưởng?
ahmed

ahmed Bạn có nghĩa là, Không bạn không, hoặc có bạn làm? (không xúc phạm tiếng Anh của bạn, chỉ yêu cầu làm rõ)
Malfist

@Malfist - xin lỗi :), ý tôi là tôi không quan tâm đến các giá trị trùng lặp bởi vì tôi chắc chắn không có bất kỳ giá trị nào trong trường hợp của tôi, cảm ơn một lần nữa
ahmed

3
Bạn không thể xóa các mục khỏi mảng trong C #, như bạn có thể thấy từ chương trình ví dụ này . Những gì bạn có thể làm là tạo một mảng mới, chỉ sao chép một số phần tử của bản gốc và gán lại cho biến ban đầu. Đây là những gì được thực hiện trong tất cả các câu trả lời.
Nicola Musatti

Câu trả lời:


340

Nếu bạn muốn xóa tất cả các phiên bản 4 mà không cần biết chỉ mục:

LINQ: (.NET Framework 3.5)

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

Không 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();

Nếu bạn muốn xóa chỉ trường hợp đầu tiên:

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

Không 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();

Chỉnh sửa: Chỉ trong trường hợp bạn chưa tìm ra, như Malfist đã chỉ ra, bạn cần phải nhắm mục tiêu .NET Framework 3.5 để các ví dụ mã LINQ hoạt động. Nếu bạn đang nhắm mục tiêu 2.0, bạn cần tham khảo các ví dụ Non-LINQ.


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

21

Bạn cũng có thể chuyển đổi mảng của mình thành một danh sách và gọi xóa trong danh sách. Sau đó bạn có thể chuyển đổi trở lại mảng của bạn.

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

11

Mã được viết trong câu hỏi có lỗi trong đó

Danh sách mảng của bạn chứa các chuỗi "1" "3" "4" "9" và "2" (lưu ý các khoảng trắng)

Vì vậy, IndexOf (4) sẽ không tìm thấy gì vì 4 là số nguyên và thậm chí "chuỗi" sẽ chuyển đổi thành "4" chứ không phải "4" và sẽ không có gì bị xóa.

Một danh sách mảng là cách chính xác để đi để làm những gì bạn muốn.


Danh sách <T> sẽ tốt hơn ArrayList.
Mike Scott

1
Câu trả lời này xứng đáng được nâng cao hơn. Mặc dù tôi hoàn toàn đồng ý với @MikeScott List<T>sẽ tốt hơn ArrayList, đây dường như là câu trả lời duy nhất xác định chính xác vấn đề mà OP gặp phải khi anh ấy cố gắng sử dụng ArrayList để giải quyết vấn đề ban đầu của mình. OP hiểu rằng bạn không thể thay đổi kích thước mảng, điều mà dường như không ai khác nhận thấy, và đã cố gắng sử dụng một loại có thể thay đổi được, thay vào đó, không ai khác có thể nhận thấy, và sau đó gặp phải một vấn đề khác, mà dường như không ai khác để ý
phoog

5

Câu trả lời của Balabaster là chính xác nếu bạn muốn loại bỏ tất cả các phiên bản của phần tử. Nếu bạn muốn xóa chỉ cái đầu tiên, bạn sẽ làm một cái gì đó như thế này:

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

5

Tôi đã đăng giải pháp của tôi ở đây .

Đây là một cách để xóa một phần tử mảng mà không cần sao chép sang mảng khác - chỉ trong khung của cùng một thể hiện mảng:

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

4
Thay đổi kích thước thực sự sao chép dữ liệu sang một mảng mới (trừ khi kích thước mới được thông qua là chiều dài của mảng được truyền); nó không thay đổi kích thước của thể hiện mảng đã qua. Đó là lý do tại sao nó là một tham số tham khảo. Xem tài liệu tham khảoource.microsoft.com / mscorlib / R / 71074deaf111c4e3.html .
phoog

5

Việc xóa khỏi một mảng tự nó không đơn giản, vì sau đó bạn phải xử lý thay đổi kích thước. Đây là một trong những lợi thế lớn của việc sử dụng một cái gì đó như List<int>thay thế. Nó cung cấp Remove/RemoveAt trong 2.0 và rất nhiều tiện ích mở rộng LINQ cho 3.0.

Nếu bạn có thể, tái cấu trúc để sử dụng một List<>hoặc tương tự.


Tôi nghĩ đó là giải pháp tốt nhất trong trường hợp này.
Bogdan Doicin

3

Là một phần mở rộng chung, tương thích 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();
    }
}

Sử dụng:

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

0

' Để xóa các mục khỏi chuỗi dựa trên các giá trị khóa Từ điển. 'Mã 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()

0

Bạn có thể làm theo cách này:

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();        
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.