Tôi có một mảng các đối tượng Foo. Làm thế nào để tôi loại bỏ phần tử thứ hai của mảng?
Tôi cần một cái gì đó tương tự RemoveAt()
nhưng cho một mảng thông thường.
Tôi có một mảng các đối tượng Foo. Làm thế nào để tôi loại bỏ phần tử thứ hai của mảng?
Tôi cần một cái gì đó tương tự RemoveAt()
nhưng cho một mảng thông thường.
Câu trả lời:
Nếu bạn không muốn sử dụng Danh sách:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Bạn có thể thử phương pháp mở rộng này mà tôi chưa thực sự thử nghiệm:
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;
}
Và sử dụng nó như:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
Bản chất của mảng là chiều dài của chúng là bất biến. Bạn không thể thêm hoặc xóa bất kỳ mục mảng nào.
Bạn sẽ phải tạo một mảng mới ngắn hơn một phần tử và sao chép các mục cũ sang mảng mới, ngoại trừ phần tử bạn muốn xóa.
Vì vậy, có lẽ tốt hơn là sử dụng Danh sách thay vì một mảng.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
sử dụng Enumerable.ToList()
phương thức từ System.Linq
không gian tên.
Tôi sử dụng phương pháp này để loại bỏ một phần tử khỏi một mảng đối tượng. Trong tình huống của tôi, mảng của tôi có chiều dài nhỏ. Vì vậy, nếu bạn có mảng lớn, bạn có thể cần một giải pháp khác.
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;
}
Giải pháp một dòng LINQ:
myArray = myArray.Where((source, index) => index != 1).ToArray();
Trong 1
ví dụ đó là chỉ mục của phần tử cần loại bỏ - trong ví dụ này, theo câu hỏi ban đầu, phần tử thứ 2 (với 1
phần tử thứ hai trong lập chỉ mục mảng dựa trên C # zero).
Một ví dụ đầy đủ hơn:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Sau khi chạy đoạn mã đó, giá trị của myArray
sẽ là { "a", "c", "d", "e" }
.
Đây là một cách để xóa một phần tử mảng, kể từ .Net 3.5, mà không sao chép sang một mảng khác - sử dụng cùng một thể hiện mảng với 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
khi bạn gọi Resize
phương thức. Độ dài của một thể hiện mảng là cố định và bất biến.
Đây là một phiên bản cũ mà tôi có, hoạt động trên phiên bản 1.0 của .NET framework và không cần các loại chung chung.
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;
}
Điều này được sử dụng như thế này:
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]);
}
}
Không chính xác cách để giải quyết vấn đề này, nhưng nếu tình huống này không quan trọng và bạn coi trọng thời gian của mình, bạn có thể thử điều này cho các loại không thể.
Foos[index] = null
và sau đó kiểm tra các mục rỗng trong logic của bạn ..
Như thường lệ, tôi đến bữa tiệc muộn ...
Tôi muốn thêm một tùy chọn khác vào danh sách giải pháp tốt đẹp đã có. =)
Tôi sẽ xem đây là một cơ hội tốt cho Tiện ích mở rộng.
Tham khảo:
http://msdn.microsoft.com/en-us/l Library / bb311042.aspx
Vì vậy, chúng tôi định nghĩa một số lớp tĩnh và trong đó, Phương thức của chúng tôi.
Sau đó, chúng ta có thể sử dụng phương pháp mở rộng của mình 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"
*/
}
}
}
Hãy thử mã dưới đây:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
hoặc là
myArray = myArray.Where(s => (s != "not_this")).ToArray();
Đây là cách tôi đã làm ...
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;
}
Đây là một bộ sưu tập nhỏ các phương thức trợ giúp tôi tạo ra dựa trên một số câu trả lời hiện có. Nó sử dụng cả phần mở rộng và phương thức tĩnh với các tham số tham chiếu để có tính lý tưởng tối đa:
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;
}
}
Hiệu suất khôn ngoan, nó là tốt, nhưng nó có thể được cải thiện. Remove
dựa vào IndexOf
và một mảng mới được tạo cho mỗi phần tử bạn muốn loại bỏ bằng cách gọi RemoveAt
.
IndexOf
là phương thức mở rộng duy nhất vì nó không cần trả về mảng ban đầu. New
chấp nhận nhiều yếu tố của một số loại để tạo ra một mảng mới của loại đã nói. Tất cả các phương thức khác phải chấp nhận mảng ban đầu làm tham chiếu, do đó không cần gán kết quả sau đó vì điều đó đã xảy ra trong nội bộ.
Tôi đã định nghĩa một Merge
phương thức để hợp nhất hai mảng; tuy nhiên, điều đó đã có thể được thực hiện bằng Add
phương thức bằng cách chuyển vào một mảng thực tế so với nhiều phần tử riêng lẻ. Do đó, Add
có thể được sử dụng theo hai cách sau để nối hai bộ phần tử:
Arr.Add<string>(ref myArray, "A", "B", "C");
Hoặc là
Arr.Add<string>(ref myArray, anotherArray);
Tôi biết bài viết này đã mười tuổi và do đó có lẽ đã chết, nhưng đây là những gì tôi sẽ thử làm:
Sử dụng phương thức IEnumerable.Skip (), được tìm thấy trong System.Linq . Nó sẽ bỏ qua phần tử được chọn từ mảng và trả về một bản sao khác của mảng chỉ chứa mọi thứ trừ đối tượng được chọn. Sau đó, chỉ cần lặp lại rằng cho mọi phần tử bạn muốn loại bỏ và sau đó lưu nó vào một biến.
Ví dụ: nếu chúng ta có một mảng có tên "Mẫu" (thuộc kiểu int []) với 5 số. Chúng tôi muốn xóa cái thứ 2, vì vậy hãy thử "Sample.Skip (2);" sẽ trả về cùng một mảng trừ khi không có số thứ 2.
Bước đầu tiên
Bạn cần chuyển đổi mảng thành một danh sách, bạn có thể viết một phương thức mở rộng như thế này
// 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;
}
Bước thứ hai
Viết phương thức mở rộng để chuyển đổi danh sách thành một mảng
// 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;
}
Các bước cuối cùng
Viết phương thức cuối cùng của bạn, nhưng nhớ xóa phần tử tại chỉ mục trước khi chuyển đổi trở lại một mảng như hiển thị mã
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
mã ví dụ có thể được tìm thấy trên blog của tôi , tiếp tục theo dõi.
.ToArray()
và một nhà List<T>
xây dựng có trình tự hiện có ...
System.Collections.ObjectModel.Collection<Foo>
.