C#.netの既存の文字列配列に新しい項目を追加する方法
既存のデータを保持する必要があります。
C#.netの既存の文字列配列に新しい項目を追加する方法
既存のデータを保持する必要があります。
回答:
動的なサイズの配列が必要な場合は、リストを使用します。
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 }小さい1項目の一時的な配列を作成するため、気に入らない人もいます。これは、Enumerable.Repeatオブジェクトを作成する必要のないバージョンを使用しています(少なくとも表面上では必要ありません。.NETイテレータは、おそらくテーブルの下に一連のステートマシンオブジェクトを作成します)。
arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();
また、配列がnull最初からないことを確信している場合は、次のように単純化できます。
arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();
順序付けられたコレクションにアイテムを追加する場合List、は、最初に配列ではなく、おそらく必要なデータ構造であることに注意してください。
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 <T>です。これらは不変の配列を含み、必要に応じてサイズを変更します(List <T>はリンクリストの実装ではありません!)。ArrayListは、ジェネリックなし(オブジェクト配列あり)と同じです。
LinkedList <T>は実際のリンクリストの実装です。残念ながら、LinkListNode <T>要素だけをリストに追加できるので、独自のリスト要素をこのノードタイプにラップする必要があります。その使用は珍しいと思います。
Aray.Resize内容を失うことなく配列のサイズを変更できると思います。docs.microsoft.com/en-us/dotnet/api/...
@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();
何らかの理由でリストではなく配列で多くの作業をしている場合、このジェネリック型付きジェネリックメソッド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のリストは、アイテムが追加されたときに内部配列のサイズが変更されないように、いくつかの余分なスペースを持つバッファースペースを持つ配列です。
すべての抽象化は同じ問題を解決し、すべての値を保持してそれらを返す空のスロットのない配列を作成する必要があります。
柔軟性が必要な場合は、渡すために使用できる十分に大きなリストを作成できます。それ以外の場合は、配列を使用してそのスレッドセーフオブジェクトを共有します。また、新しいスパンにより、リストをコピーすることなくデータを共有できます。
質問に答えるには:
Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
したがって、既存のアレイがある場合、私の簡単な修正は
var tempList = originalArray.ToList();
tempList.Add(newitem);
次に、元のアレイを新しいアレイに置き換えます
originalArray = tempList.ToArray();
新しいAppend<TSource>メソッドが追加されましたIEnumerable<TSource>.NET Framework 4.7.1および.NET Core 1.0以降、ています。
使用方法は次のとおりです。
var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four
配列の先頭に要素を追加する場合は、Prepend<TSource>代わりに新しいメソッドを使用できることに注意してください。
拡張メソッドの使用についてはどうですか?例えば:
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拡張機能(2つの配列を新しい配列に結合するために使用)のこの動作を模倣しており、Linqライブラリーが機能する必要があることに注意してください。
私はエドに同意します。C#は、VBがReDim Preserveで行うようにこれを容易にしません。コレクションがない場合は、配列をより大きな配列にコピーする必要があります。
ReDim Preserve単に配列を大きい配列にコピーします。奇跡的な配列のサイズ変更はありません。
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();
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をご覧ください。
この質問は提供された回答に満足していないため、この回答を追加したいと思います:)
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;
}
}
}
}