int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int[] z = // your answer here...
Debug.Assert(z.SequenceEqual(new int[] { 1, 2, 3, 4, 5 }));
今私は
int[] z = x.Concat(y).ToArray();
より簡単またはより効率的な方法はありますか?
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int[] z = // your answer here...
Debug.Assert(z.SequenceEqual(new int[] { 1, 2, 3, 4, 5 }));
今私は
int[] z = x.Concat(y).ToArray();
より簡単またはより効率的な方法はありますか?
回答:
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
params
パラメーターです。
System.IO.Directory.GetFiles()
、文字列の配列を返します。
これを試して:
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
List<int> list = new List<int>(x);
あなたは拡張メソッドを書くことができます:
public static T[] Concat<T>(this T[] x, T[] y)
{
if (x == null) throw new ArgumentNullException("x");
if (y == null) throw new ArgumentNullException("y");
int oldLen = x.Length;
Array.Resize<T>(ref x, x.Length + y.Length);
Array.Copy(y, 0, x, oldLen, y.Length);
return x;
}
次に:
int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}
Copy
速いですCopyTo
か?詳しく説明しますか?
同じタイプの1次元配列の任意のセットを連結できる、より汎用的なソリューションを採用しました。(一度に3つ以上を連結していました。)
私の機能:
public static T[] ConcatArrays<T>(params T[][] list)
{
var result = new T[list.Sum(a => a.Length)];
int offset = 0;
for (int x = 0; x < list.Length; x++)
{
list[x].CopyTo(result, offset);
offset += list[x].Length;
}
return result;
}
そして使い方:
int[] a = new int[] { 1, 2, 3 };
int[] b = new int[] { 4, 5, 6 };
int[] c = new int[] { 7, 8 };
var y = ConcatArrays(a, b, c); //Results in int[] {1,2,3,4,5,6,7,8}
params T[][]
さthis T[][]
れました。
これだよ:
using System.Linq;
int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };
// Concatenate array1 and array2.
var result1 = array1.Concat(array2);
int[] result = array1.ToList().Concat(array2.ToList()).toArray();
つまり、アレイにConcatを直接適用することはできないということです
toArray()
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string[]'. An explicit conversion exists (are you missing a cast?)
int[] result = ?
、あなたはvar
あなたの結果がでIEnumerable<int>
はなく、ということであなたの後ろにあなたの答えの問題を隠していますint[]
。(var
メソッドのリターンが気に入らない理由の1つ)
.ToArray()
呼び出しがないと、このコードは実際の配列を返さないため、不正解でもあります。
OPがパフォーマンスに少し興味があるだけだったことは知っています。その大きな配列は異なる結果を得る可能性があります(@kurdishTreeを参照)。そして、それは通常問題ではありません(@ jordan.peoples)。それでもなお、私は好奇心が強いので心を失いました(@TigerSharkが説明していたように)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace concat
{
class Program
{
static void Main(string[] args)
{
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int itter = 50000;
Console.WriteLine("test iterations: {0}", itter);
DateTime startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
int[] z;
z = x.Concat(y).ToArray();
}
Console.WriteLine ("Concat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
var vz = new int[x.Length + y.Length];
x.CopyTo(vz, 0);
y.CopyTo(vz, x.Length);
}
Console.WriteLine ("CopyTo Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
}
Console.WriteLine("list.AddRange Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.Concat(x, y);
}
Console.WriteLine("Concat(x, y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArrays(x, y);
}
Console.WriteLine("ConcatArrays Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.SSConcat(x, y);
}
Console.WriteLine("SSConcat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int k = 0; k < itter; k++)
{
int[] three = new int[x.Length + y.Length];
int idx = 0;
for (int i = 0; i < x.Length; i++)
three[idx++] = x[i];
for (int j = 0; j < y.Length; j++)
three[idx++] = y[j];
}
Console.WriteLine("Roll your own Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLinq(x, y);
}
Console.WriteLine("ConcatArraysLinq Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLambda(x, y);
}
Console.WriteLine("ConcatArraysLambda Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
List<int> targetList = new List<int>(x);
targetList.Concat(y);
}
Console.WriteLine("targetList.Concat(y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] result = x.ToList().Concat(y.ToList()).ToArray();
}
Console.WriteLine("x.ToList().Concat(y.ToList()).ToArray() Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
}
}
static class Methods
{
public static T[] Concat<T>(this T[] x, T[] y)
{
if (x == null) throw new ArgumentNullException("x");
if (y == null) throw new ArgumentNullException("y");
int oldLen = x.Length;
Array.Resize<T>(ref x, x.Length + y.Length);
Array.Copy(y, 0, x, oldLen, y.Length);
return x;
}
public static T[] ConcatArrays<T>(params T[][] list)
{
var result = new T[list.Sum(a => a.Length)];
int offset = 0;
for (int x = 0; x < list.Length; x++)
{
list[x].CopyTo(result, offset);
offset += list[x].Length;
}
return result;
}
public static T[] SSConcat<T>(this T[] first, params T[][] arrays)
{
int length = first.Length;
foreach (T[] array in arrays)
{
length += array.Length;
}
T[] result = new T[length];
length = first.Length;
Array.Copy(first, 0, result, 0, first.Length);
foreach (T[] array in arrays)
{
Array.Copy(array, 0, result, length, array.Length);
length += array.Length;
}
return result;
}
public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
return (from array in arrays
from arr in array
select arr).ToArray();
}
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
}
}
結果は:
自分の勝ちを振りましょう。
CopyTo
、最も高速で、の3倍高速になることがわかりましたRoll your own
。
Concat
メソッドに注意してください。C#のポスト配列連結では、次のように説明されています。
var z = x.Concat(y).ToArray();
大規模な配列の場合は非効率的です。つまり、このConcat
メソッドは中規模のサイズの配列(最大10000要素)専用です。
public static T[] Concat<T>(this T[] first, params T[][] arrays)
{
int length = first.Length;
foreach (T[] array in arrays)
{
length += array.Length;
}
T[] result = new T[length];
length = first.Length;
Array.Copy(first, 0, result, 0, first.Length);
foreach (T[] array in arrays)
{
Array.Copy(array, 0, result, length, array.Length);
length += array.Length;
}
return result;
}
Buffer.BlockCopy
over を使用するとArray.CopyTo
、より効率的(高速)になります。
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int[] z = new int[x.Length + y.Length];
var byteIndex = x.Length * sizeof(int);
Buffer.BlockCopy(x, 0, z, 0, byteIndex);
Buffer.BlockCopy(y, 0, z, byteIndex, y.Length * sizeof(int));
私のマシンでは、「ジッターをウォームアップ」する簡単なテストプログラムを作成し、リリースモードでコンパイルして、デバッガーを接続せずに実行しました。
問題の例の10,000,000回の反復の場合
Concatは3088msかかりました
CopyToは1079ミリ秒かかりました
BlockCopyは603msかかりました
テスト配列を0〜99の2つのシーケンスに変更すると、次のような結果が得られます。
Concatは45945msかかりました
CopyToは2230msかかりました
BlockCopyには1689ミリ秒かかりました
これらの結果から、CopyTo
およびBlockCopy
メソッドはConcat
、パフォーマンスが目標である場合よりもはるかに効率的であり、さらにBlockCopy
が価値があると断言できますCopyTo
。
この答えを警告するには、パフォーマンスが重要でない場合、または反復がほとんどない場合は、最も簡単な方法を選択してください。Buffer.BlockCopy
この質問の範囲を超えて型変換のためのいくつかのユーティリティを提供しています。
古いスレッドを復活させて申し訳ありませんが、これはどうですか:
static IEnumerable<T> Merge<T>(params T[][] arrays)
{
var merged = arrays.SelectMany(arr => arr);
foreach (var t in merged)
yield return t;
}
次に、コードで:
int[] x={1, 2, 3};
int[] y={4, 5, 6};
var z=Merge(x, y); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
あなたがコールするまで.ToArray()
、.ToList()
または.ToDictionary(...)
、メモリが割り当てられていない、あなたはそれを実行すると、これら3つのいずれかのコール1「クエリを構築する」または単に使用することによって、それらすべてを通過するのは自由ですforeach (var i in z){...}
から、一度にアイテムを返す句をyield return t;
上...
上記の関数は、次のように拡張できます。
static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
var merged = array1.Concat(array2);
foreach (var t in merged)
yield return t;
}
したがって、コードでは次のようなことができます。
int[] x1={1, 2, 3};
int[] x2={4, 5, 6};
int[] x3={7, 8};
var z=x1.Merge(x2).Merge(x3); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
残りは以前と同じです。
これに対するもう1つの改善は、これらの関数が単なる配列以外のものも受け入れるようにするためT[]
にIEnumerable<T>
(そうparams T[][]
なるparams IEnumerable<T>[]
)に変更することです。
お役に立てれば。
あなたはそれをあなたが参照した方法で行うことができます、またはあなたがそれについて本当に手に入れたいならあなたはあなた自身のループをロールすることができます:
string[] one = new string[] { "a", "b" };
string[] two = new string[] { "c", "d" };
string[] three;
three = new string[one.Length + two.Length];
int idx = 0;
for (int i = 0; i < one.Length; i++)
three[idx++] = one[i];
for (int j = 0; j < two.Length; j++)
three[idx++] = two[j];
LINQまたはLambda式を使用したエレガントな1行のソリューションを見つけました。どちらも同じように機能します(プログラムのコンパイル時にLINQはLambdaに変換されます)。ソリューションは、任意の配列タイプおよび任意の数の配列に対して機能します。
LINQの使用:
public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
return (from array in arrays
from arr in array
select arr).ToArray();
}
Lambdaの使用:
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
私は自分の好みに合わせて両方を提供しました。パフォーマンスに関しては、@ Sergey Shteynまたは@ deepee1のソリューションは少し高速で、ラムダ式が最も低速です。所要時間は配列要素のタイプに依存しますが、何百万もの呼び出しがない限り、メソッド間に大きな違いはありません。
以下を試してください:
T[] r1 = new T[size1];
T[] r2 = new T[size2];
List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();
これが私の答えです:
int[] z = new List<string>()
.Concat(a)
.Concat(b)
.Concat(c)
.ToArray();
このメソッドは、初期化レベルで使用できます。たとえば、静的配列の静的連結を定義するために使用できます。
public static int[] a = new int [] { 1, 2, 3, 4, 5 };
public static int[] b = new int [] { 6, 7, 8 };
public static int[] c = new int [] { 9, 10 };
public static int[] z = new List<string>()
.Concat(a)
.Concat(b)
.Concat(c)
.ToArray();
ただし、次の2つの注意事項があります。
Concat
メソッドは、両方の配列に対してイテレータを作成します。新しい配列を作成しないため、使用されるメモリの点で効率的です。ただし、ToArray
実際には新しい配列を作成してメモリを占有するため、後続の方法 はそのような利点を打ち消します。新しい配列。Concat
大規模な配列ではかなり非効率的です。中規模の配列にのみ使用する必要があります。パフォーマンスを目指すことが必要な場合は、代わりに次の方法を使用できます。
/// <summary>
/// Concatenates two or more arrays into a single one.
/// </summary>
public static T[] Concat<T>(params T[][] arrays)
{
// return (from array in arrays from arr in array select arr).ToArray();
var result = new T[arrays.Sum(a => a.Length)];
int offset = 0;
for (int x = 0; x < arrays.Length; x++)
{
arrays[x].CopyTo(result, offset);
offset += arrays[x].Length;
}
return result;
}
または(ワンライナーファンの場合):
int[] z = (from arrays in new[] { a, b, c } from arr in arrays select arr).ToArray();
後者の方がはるかにエレガントですが、前者の方がパフォーマンスが明らかに優れています。
10000要素未満の小さな配列の場合:
using System.Linq;
int firstArray = {5,4,2};
int secondArray = {3,2,1};
int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();
static class Extensions
{
public static T[] Concat<T>(this T[] array1, params T[] array2) => ConcatArray(array1, array2);
public static T[] ConcatArray<T>(params T[][] arrays)
{
int l, i;
for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++);
var a = new T[l];
for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++)
arrays[i].CopyTo(a, l);
return a;
}
}
上記の解決策は、ここで見た他の解決策よりも一般的で軽量だと思います。2つの配列のみの連結を制限しないためより一般的であり、LINQもListも使用しないため軽量です。
ソリューションは簡潔であり、一般性が追加されても、実行時のオーバーヘッドが大幅に増えることはありません。
int [] x = new int [] {1、2、3}; int [] y = new int [] {4、5};
int [] z = x.Union(y).ToArray();
Union
Distinct
結合されたコレクションから重複を暗黙的に呼び出して削除するため、これを行うにはあまり良い方法ではありません。Concat
はるかに良いですが、それは元の質問に既にあります。
int[] scores = { 100, 90, 90, 80, 75, 60 };
int[] alice = { 50, 65, 77, 90, 102 };
int[] scoreBoard = new int[scores.Length + alice.Length];
int j = 0;
for (int i=0;i<(scores.Length+alice.Length);i++) // to combine two arrays
{
if(i<scores.Length)
{
scoreBoard[i] = scores[i];
}
else
{
scoreBoard[i] = alice[j];
j = j + 1;
}
}
for (int l = 0; l < (scores.Length + alice.Length); l++)
{
Console.WriteLine(scoreBoard[l]);
}