提问人:leora 提问时间:1/19/2009 最后编辑:Peter Mortensenleora 更新时间:11/3/2023 访问量:518115
删除常规数组的元素
Remove element of a regular array
答:
这是我是如何做到的......
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;
}
数组的本质是它们的长度是不可变的。不能添加或删除任何数组项。
您必须创建一个短一个元素的新数组,并将旧项目复制到新数组中,但不包括要删除的元素。
因此,最好使用 List 而不是数组。
评论
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
Enumerable.ToList()
System.Linq
在普通数组中,必须将所有大于 2 的数组条目洗牌,然后使用 Resize 方法调整其大小。最好使用 ArrayList。
如果您不想使用 List:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
您可以尝试这个我尚未实际测试的扩展方法:
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;
}
并像这样使用它:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
评论
这是我拥有的旧版本,它适用于 .NET Framework 1.0 版,不需要泛型类型。
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;
}
这是这样用的:
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]);
}
}
我使用此方法从对象数组中删除元素。在我的情况下,我的数组长度很小。因此,如果您有大型阵列,则可能需要另一种解决方案。
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;
}
评论
不完全是解决这个问题的方法,但如果情况微不足道,并且你珍惜你的时间,你可以尝试这个可为 null 的类型。
Foos[index] = null
然后检查逻辑中的 null 条目。.
评论
第一步
你需要将数组转换成一个列表,你可以写一个这样的扩展方法
// 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;
}
第二步
:编写扩展方法,将列表转换回数组
// 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;
}
最后一步
编写最终方法,但请记住在转换回数组之前删除索引处的元素,如代码所示
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
示例代码可以在我的博客上找到,请继续跟踪。
评论
.ToArray()
List<T>
从 .Net 3.5 开始,这是一种删除数组元素的方法,而无需复制到另一个数组 - 使用具有 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
Resize
像往常一样,我参加聚会迟到了......
我想在已经存在的不错的解决方案列表中添加另一个选项。=)
我认为这是扩展的好机会。
参考资料: http://msdn.microsoft.com/en-us/library/bb311042.aspx
因此,我们定义了一些静态类,并在其中定义了我们的方法。
之后,我们可以随意使用我们的扩展方法。=)
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"
*/
}
}
}
LINQ 单线解决方案:
myArray = myArray.Where((source, index) => index != 1).ToArray();
在该示例中,是要删除的元素的索引 -- 在此示例中,根据原始问题,第 2 个元素(在 C# 从零开始的数组索引中是第二个元素)。1
1
一个更完整的例子:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
运行该代码段后,的值将为 。myArray
{ "a", "c", "d", "e" }
评论
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;
}
评论
这是我根据一些现有答案制作的一小部分帮助程序方法。它利用扩展和静态方法以及参考参数来实现最大理想性:
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;
}
}
性能方面,它不错,但可能会有所改进。 依赖,并通过调用 为要删除的每个元素创建一个新数组。Remove
IndexOf
RemoveAt
IndexOf
是唯一的扩展方法,因为它不需要返回原始数组。 接受某种类型的多个元素以生成该类型的新数组。所有其他方法都必须接受原始数组作为引用,因此无需在之后分配结果,因为这已经在内部发生。New
我会定义一个合并两个数组的方法;但是,这已经可以通过传入实际数组而不是多个单个元素来使用 method 来实现。因此,可以采用以下两种方式来连接两组元素:Merge
Add
Add
Arr.Add<string>(ref myArray, "A", "B", "C");
或
Arr.Add<string>(ref myArray, anotherArray);
我知道这篇文章已经有十年的历史了,因此可能已经死了,但这是我会尝试做的事情:
使用 System.Linq 中的 IEnumerable.Skip() 方法。它将跳过数组中的选定元素,并返回数组的另一个副本,该副本仅包含除所选对象之外的所有内容。然后,只需对要删除的每个元素重复此操作,然后将其保存到变量中。
例如,如果我们有一个名为“Sample”(类型为 int[])的数组,其中包含 5 个数字。我们想删除第二个数组,所以尝试 “Sample.Skip(2);” 应该返回相同的数组,但没有第二个数字。
评论
请尝试以下代码:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
或
myArray = myArray.Where(s => (s != "not_this")).ToArray();
嗯。为什么每个人都要分配一个新阵列?
只需将“removed”元素后面的部分向下复制一个索引,并将 null 或 default 放在最终元素中。
然后,您可以获得固定长度数组的好处(如果不使用列表,可能很重要),同时也不需要遍历每个元素检查 null(在第一个 null 时中断循环)。
评论
System.Collections.ObjectModel.Collection<Foo>