Ich habe eine Reihe von Foo-Objekten. Wie entferne ich das zweite Element des Arrays?
Ich brauche etwas Ähnliches, RemoveAt()aber für ein normales Array.
Ich habe eine Reihe von Foo-Objekten. Wie entferne ich das zweite Element des Arrays?
Ich brauche etwas Ähnliches, RemoveAt()aber für ein normales Array.
Antworten:
Wenn Sie List nicht verwenden möchten:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Sie können diese Erweiterungsmethode ausprobieren, die ich noch nicht getestet habe:
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;
}
Und benutze es wie:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
Die Natur von Arrays ist, dass ihre Länge unveränderlich ist. Sie können keine Array-Elemente hinzufügen oder löschen.
Sie müssen ein neues Array erstellen, das ein Element kürzer ist, und die alten Elemente in das neue Array kopieren, mit Ausnahme des Elements, das Sie löschen möchten.
Daher ist es wahrscheinlich besser, eine Liste anstelle eines Arrays zu verwenden.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();mit der Enumerable.ToList()Methode aus dem System.LinqNamespace.
Ich benutze diese Methode, um ein Element aus einem Objektarray zu entfernen. In meiner Situation sind meine Arrays klein. Wenn Sie also große Arrays haben, benötigen Sie möglicherweise eine andere Lösung.
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;
}
Einzeilige LINQ-Lösung:
myArray = myArray.Where((source, index) => index != 1).ToArray();
Das 1in diesem Beispiel ist der Index des zu entfernenden Elements - in diesem Beispiel gemäß der ursprünglichen Frage das zweite Element (wobei 1es das zweite Element bei der C # -Null-basierten Array-Indizierung ist).
Ein vollständigeres Beispiel:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Danach Snippet ausgeführt wird , der Wert myArraysein wird { "a", "c", "d", "e" }.
Auf diese Weise können Sie ein Array-Element ab .Net 3.5 löschen, ohne es in ein anderes Array zu kopieren. Verwenden Sie dazu dieselbe Array-Instanz mit 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);
}
refbeim Aufrufen der ResizeMethode verwenden. Die Länge einer Array-Instanz ist fest und unveränderlich.
Hier ist eine alte Version, die auf Version 1.0 des .NET Frameworks funktioniert und keine generischen Typen benötigt.
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;
}
Dies wird folgendermaßen verwendet:
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]);
}
}
Nicht genau der richtige Weg, aber wenn die Situation trivial ist und Sie Ihre Zeit schätzen, können Sie dies für nullbare Typen versuchen.
Foos[index] = null
und später nach Null-Einträgen in Ihrer Logik suchen.
Wie immer bin ich zu spät zur Party ...
Ich möchte der bereits vorhandenen Liste der netten Lösungen eine weitere Option hinzufügen. =)
Ich würde dies als eine gute Gelegenheit für Erweiterungen sehen.
Referenz:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Also definieren wir eine statische Klasse und darin unsere Methode.
Danach können wir unsere erweiterte Methode wohl oder übel anwenden. =)
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"
*/
}
}
}
Versuchen Sie den folgenden Code:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
oder
myArray = myArray.Where(s => (s != "not_this")).ToArray();
So habe ich es gemacht ...
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;
}
Hier ist eine kleine Sammlung von Hilfsmethoden, die ich basierend auf einigen der vorhandenen Antworten erstellt habe. Es verwendet sowohl Erweiterungen als auch statische Methoden mit Referenzparametern für maximale Idealität:
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;
}
}
In Bezug auf die Leistung ist es anständig, aber es könnte wahrscheinlich verbessert werden. Removeverlässt sich darauf IndexOfund für jedes Element, das Sie durch Aufrufen entfernen möchten, wird ein neues Array erstellt RemoveAt.
IndexOfist die einzige Erweiterungsmethode, da das ursprüngliche Array nicht zurückgegeben werden muss. Newakzeptiert mehrere Elemente eines Typs, um ein neues Array dieses Typs zu erzeugen. Alle anderen Methoden müssen das ursprüngliche Array als Referenz akzeptieren, sodass das Ergebnis nicht später zugewiesen werden muss, da dies bereits intern geschieht.
Ich hätte eine MergeMethode zum Zusammenführen von zwei Arrays definiert. Dies kann jedoch bereits mit der AddMethode erreicht werden, indem ein tatsächliches Array gegenüber mehreren einzelnen Elementen übergeben wird. Daher Addkann auf zwei Arten verwendet werden, um zwei Sätze von Elementen zu verbinden:
Arr.Add<string>(ref myArray, "A", "B", "C");
Oder
Arr.Add<string>(ref myArray, anotherArray);
Ich weiß, dass dieser Artikel zehn Jahre alt und daher wahrscheinlich tot ist, aber ich würde Folgendes versuchen:
Verwenden Sie die IEnumerable.Skip () -Methode in System.Linq . Das ausgewählte Element wird aus dem Array übersprungen und eine weitere Kopie des Arrays zurückgegeben, die nur alles außer dem ausgewählten Objekt enthält. Wiederholen Sie dies dann einfach für jedes Element, das Sie entfernen möchten, und speichern Sie es anschließend in einer Variablen.
Zum Beispiel, wenn wir ein Array mit dem Namen "Sample" (vom Typ int []) mit 5 Zahlen haben. Wir wollen den zweiten entfernen und versuchen "Sample.Skip (2);" sollte das gleiche Array zurückgeben, außer ohne die 2. Nummer.
Erster Schritt
Sie müssen das Array in eine Liste konvertieren. Sie können eine Erweiterungsmethode wie diese schreiben
// 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;
}
Zweiter Schritt
Schreiben Sie eine Erweiterungsmethode, um die Liste wieder in ein Array zu konvertieren
// 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;
}
Letzte Schritte
Schreiben Sie Ihre endgültige Methode, aber denken Sie daran, das Element am Index zu entfernen, bevor Sie es wieder in ein Array wie den Code show konvertieren
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
Beispielcodes finden Sie in meinem Blog .
.ToArray()List<T>
System.Collections.ObjectModel.Collection<Foo>.