Bir dizi Foo nesnem var. Dizinin ikinci elemanını nasıl kaldırırım?
Benzer bir şeye ihtiyacım var RemoveAt()ama normal bir dizi için.
Bir dizi Foo nesnem var. Dizinin ikinci elemanını nasıl kaldırırım?
Benzer bir şeye ihtiyacım var RemoveAt()ama normal bir dizi için.
Yanıtlar:
Listeyi kullanmak istemiyorsanız:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Aslında test etmediğim bu uzantı yöntemini deneyebilirsiniz:
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;
}
Ve şu şekilde kullanın:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
Dizilerin doğası, uzunluklarının değişmez olmasıdır. Dizi öğelerinin hiçbirini ekleyemez veya silemezsiniz.
Bir öğe daha kısa olan yeni bir dizi oluşturmanız ve silmek istediğiniz öğeyi hariç tutarak eski öğeleri yeni diziye kopyalamanız gerekecektir.
Bu yüzden bir dizi yerine Liste kullanmak muhtemelen daha iyidir.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();kullanarak . Enumerable.ToList()System.Linq
Nesne dizisinden bir öğeyi kaldırmak için bu yöntemi kullanıyorum. Benim durumumda dizilerimin uzunluğu küçük. Yani büyük dizileriniz varsa başka bir çözüme ihtiyacınız olabilir.
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;
}
LINQ tek satırlık çözüm:
myArray = myArray.Where((source, index) => index != 1).ToArray();
Bu 1örnekteki, kaldırılacak öğenin dizinidir - bu örnekte, orijinal soruya göre, 2. öğe ( 1C # sıfır tabanlı dizi indekslemede ikinci öğedir).
Daha eksiksiz bir örnek:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Bu parçacığı çalıştırdıktan sonra değeri myArrayolacaktır { "a", "c", "d", "e" }.
Bu, .Net 3.5'ten itibaren bir dizi öğesini başka bir diziye kopyalamadan - aynı dizi örneğini kullanarak silmenin bir yoludur 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çağırdığınızda bu yüzden kullanmanız gerekir Resize. Bir dizi örneğinin uzunluğu sabittir ve değişmez.
İşte .NET çerçevesinin 1.0 sürümünde çalışan ve genel türlere ihtiyaç duymayan eski bir sürümüm var.
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;
}
Bu şu şekilde kullanılır:
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]);
}
}
Tam olarak bunu yapmanın yolu değil, ancak durum önemsizse ve zamanınıza değer veriyorsanız, bunu null yapılabilir türler için deneyebilirsiniz.
Foos[index] = null
ve daha sonra mantığınızda boş girdileri kontrol edin ..
Her zamanki gibi partiye geç kaldım ...
Zaten mevcut olan güzel çözümler listesine başka bir seçenek eklemek istiyorum. =)
Bunu Uzantılar için iyi bir fırsat olarak görürdüm.
Referans:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Bu nedenle, bazı statik sınıfları ve içinde Metodumuzu tanımlıyoruz.
Bundan sonra, genişletilmiş yöntemimizi isteyerek kullanabiliriz. =)
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"
*/
}
}
}
Aşağıdaki kodu deneyin:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
veya
myArray = myArray.Where(s => (s != "not_this")).ToArray();
İşte böyle yaptı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;
}
İşte mevcut yanıtlardan bazılarına dayanarak ürettiğim küçük bir yardımcı yöntem koleksiyonu. Maksimum ideallik için referans parametreli hem uzantıları hem de statik yöntemleri kullanır:
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;
}
}
Performans açısından iyi, ancak muhtemelen geliştirilebilir. Removedayanır IndexOfve çağırarak kaldırmak istediğiniz her öğe için yeni bir dizi oluşturulur RemoveAt.
IndexOforijinal diziyi döndürmesi gerekmediği için tek uzantı yöntemidir. Newsöz konusu tipte yeni bir dizi üretmek için bir türden birden fazla elemanı kabul eder. Diğer tüm yöntemler, orijinal diziyi bir referans olarak kabul etmelidir, böylece daha sonra dahili olarak gerçekleştiği için sonucu daha sonra atamaya gerek yoktur.
Mergeİki diziyi birleştirmek için bir yöntem tanımlardım ; ancak, bu, Addgerçek bir diziye karşı birden çok tekil öğeye geçerek yöntemle zaten başarılabilir . Bu nedenle, Addiki öğe kümesini birleştirmek için aşağıdaki iki şekilde kullanılabilir:
Arr.Add<string>(ref myArray, "A", "B", "C");
Veya
Arr.Add<string>(ref myArray, anotherArray);
Bu makalenin on yaşında olduğunu ve bu nedenle muhtemelen öldüğünü biliyorum, ama işte yapmaya çalıştığım şey:
System.Linq'de bulunan IEnumerable.Skip () yöntemini kullanın . Diziden seçilen öğeyi atlar ve dizinin yalnızca seçilen nesne dışındaki her şeyi içeren başka bir kopyasını döndürür. Ardından, kaldırılmasını istediğiniz her öğe için bunu tekrarlayın ve ardından bir değişkene kaydedin.
Örneğin, "Sample" adında (int [] türünde) 5 sayı içeren bir dizimiz varsa. İkincisini kaldırmak istiyoruz, bu yüzden "Sample.Skip (2);" 2. sayı olmadan aynı diziyi döndürmelidir.
İlk adım
Diziyi bir listeye dönüştürmeniz gerekiyor, bunun gibi bir genişletme yöntemi yazabilirsiniz.
// 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;
}
İkinci adım
Listeyi bir diziye dönüştürmek için bir genişletme yöntemi yazın
// 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;
}
Son adımlar
Son yönteminizi yazın, ancak kod gösterisi gibi bir diziye geri dönüştürmeden önce dizindeki öğeyi kaldırmayı unutmayın.
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
örnekler kodları üzerinde bulabilmesi olabilir bloguma , izleme tutun.
.ToArray()ve List<T>... Varolan diziyi alan kurucuya
System.Collections.ObjectModel.Collection<Foo>.