在 c#.net 的现有数组中添加新项
本文关键字:数组 添加 新项 net | 更新日期: 2023-09-27 17:47:46
如何在C#.net的现有字符串数组中添加新项目?
我需要保留现有数据。
如果您需要动态大小的数组,我会使用 List:
List<string> ls = new List<string>();
ls.Add("Hello");
这可能是一个解决方案;
Array.Resize(ref array, newsize);
array[newsize - 1] = "newvalue"
但是对于动态大小的数组,我也更喜欢列表。
使用 LINQ:
arr = (arr ?? Enumerable.Empty<string>()).Concat(new[] { newitem }).ToArray();
我喜欢使用它,因为它是单行的,嵌入到 switch 语句、简单的 if 语句或作为参数传递非常方便。
编辑:
有些人不喜欢new[] { newitem }
因为它创建了一个小型的单项临时数组。 这是一个使用 Enumerable.Repeat
的版本,不需要创建任何对象(至少表面上不需要-- .NET 迭代器可能会在表下创建一堆状态机对象(。
arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();
如果您确定数组永远不会null
开始,则可以将其简化为:
arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();
请注意,如果要将项添加到有序集合中,List
可能是所需的数据结构,而不是要开始的数组。
非常老的问题,但仍然想添加这个。
如果您正在寻找单行代码,可以使用下面的代码。它结合了接受可枚举列表构造函数和"new"(自问题引发以来(初始值设定项语法。
myArray = new List<string>(myArray) { "add this" }.ToArray();
C# 中的数组是不可变的,例如 string[]
,int[]
。这意味着您无法调整它们的大小。您需要创建一个全新的阵列。
以下是 Array.Resize 的代码:
public static void Resize<T>(ref T[] array, int newSize)
{
if (newSize < 0)
{
throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
T[] sourceArray = array;
if (sourceArray == null)
{
array = new T[newSize];
}
else if (sourceArray.Length != newSize)
{
T[] destinationArray = new T[newSize];
Copy(sourceArray, 0, destinationArray, 0, (sourceArray.Length > newSize) ? newSize : sourceArray.Length);
array = destinationArray;
}
}
如您所见,它创建一个具有新大小的新数组,复制源数组的内容并设置对新数组的引用。对此的提示是第一个参数的 ref 关键字。
有些列表可以为新项目动态分配新插槽。例如,List
LinkedList
Array.Resize(ref youur_array_name, your_array_name.Length + 1);
your_array_name[your_array_name.Length - 1] = "new item";
自 .NET Framework 4.7.1 和 .NET Core 1.0 以来,IEnumerable<TSource>
添加了一种新的Append<TSource>
方法。
以下是使用它的方法:
var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four
请注意,如果要在数组的开头添加元素,则可以改用新的Prepend<TSource>
方法。
您可以使用 @Stephen Chung 提供的答案来扩展其基于 LINQ 的逻辑,以使用泛型类型创建扩展方法。
public static class CollectionHelper
{
public static IEnumerable<T> Add<T>(this IEnumerable<T> sequence, T item)
{
return (sequence ?? Enumerable.Empty<T>()).Concat(new[] { item });
}
public static T[] AddRangeToArray<T>(this T[] sequence, T[] items)
{
return (sequence ?? Enumerable.Empty<T>()).Concat(items).ToArray();
}
public static T[] AddToArray<T>(this T[] sequence, T item)
{
return Add(sequence, item).ToArray();
}
}
然后,您可以像这样直接在数组上调用它。
public void AddToArray(string[] options)
{
// Add one item
options = options.AddToArray("New Item");
// Add a
options = options.AddRangeToArray(new string[] { "one", "two", "three" });
// Do stuff...
}
诚然,AddRangeToArray(( 方法似乎有点矫枉过正,因为您与 Concat(( 具有相同的功能,但这样结束代码可以直接"工作"数组与此相反:
options = options.Concat(new string[] { "one", "two", "three" }).ToArray();
因此,如果您有一个现有的数组,我的快速解决方法将是
var tempList = originalArray.ToList();
tempList.Add(newitem);
现在只需用新数组替换原始数组
originalArray = tempList.ToArray();
最好保持数组不可变和固定大小。
您可以通过Extension Method
和IEnumerable.Concat()
来模拟Add
public static class ArrayExtensions
{
public static string[] Add(this string[] array, string item)
{
return array.Concat(new[] {item}).ToArray();
}
}
如果您由于某种原因经常使用数组而不是列表,则此泛型类型返回泛型方法Add
可能会有所帮助
public static T[] Add<T>(T[] array, T item)
{
T[] returnarray = new T[array.Length + 1];
for (int i = 0; i < array.Length; i++)
{
returnarray[i] = array[i];
}
returnarray[array.Length] = item;
return returnarray;
}
所有建议的答案都与他们所说的他们想要避免的答案相同,创建一个新数组并在其中添加一个新条目,只是丢失了更多的开销。LINQ 不是魔法,T 列表是一个带有缓冲区空间的数组,其中包含一些额外的空间,以避免在添加项目时调整内部数组的大小。
所有的抽象都必须解决同样的问题,创建一个没有空槽的数组来保存所有值并返回它们。
如果您需要灵活性,可以创建一个足够大的列表,您可以使用该列表来传递,然后这样做。 否则使用数组并共享该线程安全对象。此外,新的Span有助于共享数据,而无需复制列表。
要回答这个问题:
Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
使用列表将是内存管理的最佳选择。
string str = "string ";
List<string> li_str = new List<string>();
for (int k = 0; k < 100; i++ )
li_str.Add(str+k.ToString());
string[] arr_str = li_str.ToArray();
使用扩展方法怎么样? 例如:
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> source, TSource item)
{
return source.Union(new TSource[] { item });
}
例如:
string[] sourceArray = new []
{
"foo",
"bar"
}
string additionalItem = "foobar";
string result = sourceArray.Union(additionalItem);
请注意,这模仿了 Linq 的 Uniion 扩展(用于将两个数组合并为一个新数组(的这种行为,并且需要 Linq 库才能运行。
我同意Ed的观点。 C#并没有像VB使用ReDim Preserve那样容易做到这一点。 如果没有集合,则必须将数组复制到更大的数组中。
private static string[] GetMergedArray(string[] originalArray, string[] newArray)
{
int startIndexForNewArray = originalArray.Length;
Array.Resize<string>(ref originalArray, originalArray.Length + newArray.Length);
newArray.CopyTo(originalArray, startIndexForNewArray);
return originalArray;
}
为什么不尝试使用 Stringbuilder 类。它有.insert和.append等方法。你可以在这里阅读更多关于它的信息:http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71(.aspx<</p>
使用列表并非在所有情况下都有效。列表和数组实际上是不同的,并且不是 100% 可互换的。这将取决于情况,这是否是一种可以接受的解决方法。
由于这个问题对提供的答案不满意,我想将此答案添加到:)
public class CustomArrayList<T>
{
private T[] arr; private int count;
public int Count
{
get
{
return this.count;
}
}
private const int INITIAL_CAPACITY = 4;
public CustomArrayList(int capacity = INITIAL_CAPACITY)
{
this.arr = new T[capacity]; this.count = 0;
}
public void Add(T item)
{
GrowIfArrIsFull();
this.arr[this.count] = item; this.count++;
}
public void Insert(int index, T item)
{
if (index > this.count || index < 0)
{
throw new IndexOutOfRangeException( "Invalid index: " + index);
}
GrowIfArrIsFull();
Array.Copy(this.arr, index, this.arr, index + 1, this.count - index);
this.arr[index] = item; this.count++; }
private void GrowIfArrIsFull()
{
if (this.count + 1 > this.arr.Length)
{
T[] extendedArr = new T[this.arr.Length * 2];
Array.Copy(this.arr, extendedArr, this.count);
this.arr = extendedArr;
}
}
}
}