回答:
配列の1つを操作できる場合は、コピーを実行する前に配列のサイズを変更できます。
T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
int array1OriginalLength = array1.Length;
Array.Resize<T>(ref array1, array1OriginalLength + array2.Length);
Array.Copy(array2, 0, array1, array1OriginalLength, array2.Length);
それ以外の場合は、新しい配列を作成できます
T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
T[] newArray = new T[array1.Length + array2.Length];
Array.Copy(array1, newArray, array1.Length);
Array.Copy(array2, 0, newArray, array1.Length, array2.Length);
Array.Resize
実際には配列、それそれのコピーのサイズを変更しません。そのため、最初のパラメーターは参照渡しです(つまり、最初のコードはおそらくコンパイルされません)。
C#3.0では、LINQのConcatメソッドを使用して、これを簡単に実現できます。
int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = front.Concat(back).ToArray();
C#2.0では、そのような直接的な方法はありませんが、Array.Copyはおそらく最良のソリューションです。
int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = new int[front.Length + back.Length];
Array.Copy(front, combined, front.Length);
Array.Copy(back, 0, combined, front.Length, back.Length);
これは、独自のバージョンのを実装するために簡単に使用できますConcat
。
LINQを使用します。
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Union(arr2).ToArray();
重複を削除することに注意してください。重複を保持したい場合は、Concatを使用します。
まず、「ここで本当に配列を使用する必要があるのか」という質問を自問してください。
速度が最も重要なものを構築しているのでない限り、型付きリストは、List<int>
おそらく進むべき道です。私がこれまでに配列を使用するのは、ネットワーク経由でデータを送信するときのバイト配列のみです。それ以外は、決して触れません。
List<T>
、パブリックAPIで公開しないことです:blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx
LINQを使用する方が簡単です。
var array = new string[] { "test" }.ToList();
var array1 = new string[] { "test" }.ToList();
array.AddRange(array1);
var result = array.ToArray();
最初に配列をリストに変換してマージします...その後、リストを配列に変換し直します:)
これにはArray.Copyを使用できると思います。ソースインデックスと宛先インデックスを取得するため、1つの配列を他の配列に追加できるはずです。単に一方をもう一方に追加するよりも複雑にする必要がある場合、これは適切なツールではない可能性があります。
デスティネーションアレイに十分なスペースがあると仮定すると、Array.Copy()
動作します。List<T>
とその.AddRange()
メソッドを使用することもできます。
個人的には、ラピッドプロトタイピングのために自分で自由に追加または削除できる独自の言語拡張機能を好みます。
以下は文字列の例です。
//resides in IEnumerableStringExtensions.cs
public static class IEnumerableStringExtensions
{
public static IEnumerable<string> Append(this string[] arrayInitial, string[] arrayToAppend)
{
string[] ret = new string[arrayInitial.Length + arrayToAppend.Length];
arrayInitial.CopyTo(ret, 0);
arrayToAppend.CopyTo(ret, arrayInitial.Length);
return ret;
}
}
LINQやConcatよりもはるかに高速です。さらに速いのは、IEnumerable
渡された配列の参照/ポインタを格納し、コレクション全体を通常の配列のようにループできるカスタムタイプラッパーを使用していることです。(HPC、グラフィックス処理、グラフィックスレンダリングで役立ちます...)
あなたのコード:
var someStringArray = new[]{"a", "b", "c"};
var someStringArray2 = new[]{"d", "e", "f"};
someStringArray.Append(someStringArray2 ); //contains a,b,c,d,e,f
コード全体とジェネリックバージョンについては、https://gist.github.com/lsauer/7919764を参照してください。
注:これは、拡張されていないIEnumerableオブジェクトを返します。拡張オブジェクトを返すには少し時間がかかります。
2002年以降、このような拡張機能をコンパイルしました。多くのクレジットは、CodeProjectと 'Stackoverflow'の役立つ人々に提供されました。私はこれらをまもなくリリースし、リンクをここに配置します。
これが私が思いついたものです。可変数の配列で機能します。
public static T[] ConcatArrays<T>(params T[][] args)
{
if (args == null)
throw new ArgumentNullException();
var offset = 0;
var newLength = args.Sum(arr => arr.Length);
var newArray = new T[newLength];
foreach (var arr in args)
{
Buffer.BlockCopy(arr, 0, newArray, offset, arr.Length);
offset += arr.Length;
}
return newArray;
}
...
var header = new byte[] { 0, 1, 2};
var data = new byte[] { 3, 4, 5, 6 };
var checksum = new byte[] {7, 0};
var newArray = ConcatArrays(header, data, checksum);
//output byte[9] { 0, 1, 2, 3, 4, 5, 6, 7, 0 }
オプションとして注記しておきます。使用している配列がプリミティブ型である場合–ブール(ブール)、Char、SByte、Byte、Int16(short)、UInt16、Int32(int)、UInt32、Int64(long )、UInt64型、のIntPtr、UIntPtr、シングル、またはダブル- ?あなたは(または)を使用してみてください可能性がありBuffer.BlockCopyを。BufferクラスのMSDNページによると:
このクラスは、System.Arrayクラスの同様のメソッドよりも、プリミティブ型を操作するためのパフォーマンスが向上します。
@OwenPの回答のC#2.0の例を出発点として使用すると、次のように機能します。
int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = new int[front.Length + back.Length];
Buffer.BlockCopy(front, 0, combined, 0, front.Length);
Buffer.BlockCopy(back, 0, combined, front.Length, back.Length);
と@OwenPで使用されBuffer.BlockCopy
てArray.Copy
いるとの間で構文にほとんど違いはありませんが、これはより速くなるはずです(わずかであっても)。
他の誰かが2つの画像バイト配列をマージする方法を探している場合:
private void LoadImage()
{
string src = string.empty;
byte[] mergedImageData = new byte[0];
mergedImageData = MergeTwoImageByteArrays(watermarkByteArray, backgroundImageByteArray);
src = "data:image/png;base64," + Convert.ToBase64String(mergedImageData);
MyImage.ImageUrl = src;
}
private byte[] MergeTwoImageByteArrays(byte[] imageBytes, byte[] imageBaseBytes)
{
byte[] mergedImageData = new byte[0];
using (var msBase = new MemoryStream(imageBaseBytes))
{
System.Drawing.Image imgBase = System.Drawing.Image.FromStream(msBase);
Graphics gBase = Graphics.FromImage(imgBase);
using (var msInfo = new MemoryStream(imageBytes))
{
System.Drawing.Image imgInfo = System.Drawing.Image.FromStream(msInfo);
Graphics gInfo = Graphics.FromImage(imgInfo);
gBase.DrawImage(imgInfo, new Point(0, 0));
//imgBase.Save(Server.MapPath("_____testImg.png"), ImageFormat.Png);
MemoryStream mergedImageStream = new MemoryStream();
imgBase.Save(mergedImageStream, ImageFormat.Png);
mergedImageData = mergedImageStream.ToArray();
mergedImageStream.Close();
}
}
return mergedImageData;
}
Array.CopyToを使用した簡単な例を次に示します。私はそれがあなたの質問に答え、CopyToの使用例を示していると思います-ヘルプが少し不明確なので、この関数を使用する必要があるときはいつも困惑します-インデックスは挿入が行われる宛先配列の位置です。
int[] xSrc1 = new int[3] { 0, 1, 2 };
int[] xSrc2 = new int[5] { 3, 4, 5, 6 , 7 };
int[] xAll = new int[xSrc1.Length + xSrc2.Length];
xSrc1.CopyTo(xAll, 0);
xSrc2.CopyTo(xAll, xSrc1.Length);
あなたはそれをもっと簡単にすることはできないと思います。
未知の数の配列を組み合わせるソリューションが必要でした。
を使用SelectMany
して解決策を提供した人は他に誰もいないことに驚いたparams
。
private static T[] Combine<T>(params IEnumerable<T>[] items) =>
items.SelectMany(i => i).Distinct().ToArray();
個別のアイテムが必要ない場合は、個別を削除してください。
public string[] Reds = new [] { "Red", "Crimson", "TrafficLightRed" };
public string[] Greens = new [] { "Green", "LimeGreen" };
public string[] Blues = new [] { "Blue", "SkyBlue", "Navy" };
public string[] Colors = Combine(Reds, Greens, Blues);
注:個別を使用する場合、順序の保証はありません。
組み込みの.NET配列ではなく、独自の配列型を使用していると想定しています。
public string[] merge(input1, input2)
{
string[] output = new string[input1.length + input2.length];
for(int i = 0; i < output.length; i++)
{
if (i >= input1.length)
output[i] = input2[i-input1.length];
else
output[i] = input1[i];
}
return output;
}
これを行う別の方法は、組み込みのArrayListクラスを使用することです。
public ArrayList merge(input1, input2)
{
Arraylist output = new ArrayList();
foreach(string val in input1)
output.add(val);
foreach(string val in input2)
output.add(val);
return output;
}
どちらの例もC#です。
int [] SouceArray1 = new int[] {2,1,3};
int [] SourceArray2 = new int[] {4,5,6};
int [] targetArray = new int [SouceArray1.Length + SourceArray2.Length];
SouceArray1.CopyTo(targetArray,0);
SourceArray2.CopyTo(targetArray,SouceArray1.Length) ;
foreach (int i in targetArray) Console.WriteLine(i + " ");
上記のコードを使用すると、2つの配列を簡単にマージできます。
nullを処理するための作成および拡張メソッド
public static class IEnumerableExtenions
{
public static IEnumerable<T> UnionIfNotNull<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
{
if (list1 != null && list2 != null)
return list1.Union(list2);
else if (list1 != null)
return list1;
else if (list2 != null)
return list2;
else return null;
}
}
配列自体にソース配列がある場合は、SelectManyを使用できます。
var arrays = new[]{new[]{1, 2, 3}, new[]{4, 5, 6}};
var combined = arrays.SelectMany(a => a).ToArray();
foreach (var v in combined) Console.WriteLine(v);
与える
1
2
3
4
5
6
おそらくこれは最速の方法ではありませんが、ユースケースによっては適合する場合があります。
このコードはすべてのケースで機能します。
int[] a1 ={3,4,5,6};
int[] a2 = {4,7,9};
int i = a1.Length-1;
int j = a2.Length-1;
int resultIndex= i+j+1;
Array.Resize(ref a2, a1.Length +a2.Length);
while(resultIndex >=0)
{
if(i != 0 && j !=0)
{
if(a1[i] > a2[j])
{
a2[resultIndex--] = a[i--];
}
else
{
a2[resultIndex--] = a[j--];
}
}
else if(i>=0 && j<=0)
{
a2[resultIndex--] = a[i--];
}
else if(j>=0 && i <=0)
{
a2[resultIndex--] = a[j--];
}
}