C#で2つの配列を連結するにはどうすればよいですか?


267
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();

より簡単またはより効率的な方法はありますか?


8
「効率的」とはどういう意味ですか?コードは十分に短いので、CPU / RAMの点で効率的だと思いますか?
TToni、2009年

4
いいえ、Reflectorを
ざっと

zがint []型である必要があることを明確にしてください。
hwiechers、2009年

4
効率についてはそれほど心配していません。(私はより簡単またはより効率的だと言いました。)他の人々がこの一般的なタスクをどのように処理していたかを確認するために質問をしました。
hwiechers

回答:


331
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);

8
@manthrax->その防御として、C#は配列よりもはるかに強力なリストを好む傾向があります。配列を使用する唯一の機能的な目的は、相互運用呼び出し(アンマネージC ++)のためです。
Levi Fuller

@LeviFuller C#が配列を使用するもう1つの場所は、可変数paramsパラメーターです。
ChrisW、2016年

1
@LeviFuller-多くのシステムルーチンがリストではなく配列を返すのは奇妙です。たとえばSystem.IO.Directory.GetFiles()、文字列の配列を返します。
orion elenzil 2016年

4
これは奇妙ではありません。配列は不変で、リストはありません。また、TrimExcessが呼び出されない限り、リストは配列よりも多くのメモリを使用します(ToListでは発生しません)
CSharpie

1
また、リストはデータにアクセスするときにリストよりも高速です。これは、リストが配列をラップするだけで、インデクサーを呼び出すためのオーバーヘッドがあるためです。
C0DEF52

84

これを試して:

List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();

5
またはList<int> list = new List<int>(x);
マシューシャーリー

7
それはどのようにx.Concat(y)よりも効率的ですか?それは機能し、すべて、私はそれをより良くするものがあるかどうか疑問に思っていますか?
マイク2

7
最初の行をList <int> list = new List <int>(x.Length + y.Length);にすることもできます。AddRangeを呼び出すときに発生する可能性があるサイズ変更を回避するには
Mike Two

5
@マシュー・シャーリー。問題は、より効率的なソリューションを求めていることです。タイトルが古い組み合わせのように聞こえることは知っていますが、完全な質問はそれを超えています。いくつかの回答を読んでいると、タイトルに回答している人がいるように感じます。だから私は、この回答が疑問点のように思われたので、賛成に値するなら、おそらくこの回答は効率性について言及するべきだと思いました。
マイク2、

2
AddRangeは実際には非常にコストのかかるプロセスであることが判明したため、このボードの最初の答えは推奨さ
Liam

49

あなたは拡張メソッドを書くことができます:

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}

1
IEnumerableで機能する拡張メソッドはまだありませんか?
マイク2、

2
はい、ほとんどの場合、私はそれを喜んで使用します。しかし、それらには多くのオーバーヘッドがあります。場合によります; 98%の時間でオーバーヘッドは問題ありません。ただし、2%以内であれば、直接memcopy / array作業を行うと便利です。
Marc Gravell

1
@nawfal、どのくらいCopy速いですCopyToか?詳しく説明しますか?
skrebbel

1
@skrebbel mineは不正確なコメントでした。私はそのときいくつかのテストをしました、そして私はコピーをより速く見つけました。しかし、今ではそれらはちょうど等しいようです。私が当時見つけた可能性があるのは、マルクのアプローチ全体がより効率的であり、ゼッドのアプローチでは新しい配列を作成している間、彼は同じインスタンスを返しているためです。謝罪:)
nawfal

1
@シミーそれはしません。このメソッドの内部では、xはローカル変数ですが、xをrefとしてresizeメソッドに渡すと、新しい配列が作成され、(ローカル変数)xがそれを指すように変更されます。または言い換えると、拡張メソッド内でサイズ変更に渡されるxとxは同じ変数ですが、xは参照として拡張メソッドに渡されないため、xは、この拡張が呼び出されたスコープ内の変数とは異なる変数です。
AnorZaken 2015

40

同じタイプの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[][]れました。
マーク

こんにちはみんな、この関数は私が探していたもののように見えますが、これをどのように達成するかについてのアイデアはありますか?リンク @Mark
George B

31

これだよ:

using System.Linq;

int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };

// Concatenate array1 and array2.
var result1 = array1.Concat(array2);

4
int[] result = array1.ToList().Concat(array2.ToList()).toArray();つまり、アレイにConcatを直接適用することはできないということです
ミハイルミシャイリディス2014年

4
このソリューション-z = x.Concat(y)-は、上記の元の質問で言及されています。
Jon Schneider、

1
これがなくて何が起こるかであるtoArray() Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string[]'. An explicit conversion exists (are you missing a cast?)
ティボーUdvari

2
これは直接的な答えではありません。OPが求めたint[] result = ?、あなたはvarあなたの結果がでIEnumerable<int>はなく、ということであなたの後ろにあなたの答えの問題を隠していますint[]。(varメソッドのリターンが気に入らない理由の1つ)
David S.

2
このメソッドは質問で使用されるものであるため、この回答は新しい情報を提供せず、.ToArray()呼び出しがないと、このコードは実際の配列を返さないため、不正解でもあります。
Mani Gandham 2016

10

ToArray()の呼び出しを最後まで行うことができます。Concatの呼び出し後に配列にする必要がある理由はありますか?

Concatを呼び出すと、両方の配列にイテレータが作成されます。新しいアレイは作成されないため、新しいアレイ用に多くのメモリを使用していません。ToArrayを呼び出すとき、実際には新しい配列を作成し、新しい配列のメモリを消費します。

したがって、両方を簡単に繰り返す必要がある場合は、Concatを呼び出します。


8

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();
        }
    }

}

結果は:

ここに画像の説明を入力してください

自分の勝ちを振りましょう。


メソッドを使用したメソッドに公平に、メソッドはおそらくシステムに約10,000ティックを追加しました。
アマルガメート2014年

1
私はあなたのコードをVisual Studio 2013のリリースモードで実行しましたが、テストした配列があなたの配列ほど小さくない場合(1000要素など)はCopyTo、最も高速で、の3倍高速になることがわかりましたRoll your own
リー氏、2015

@ Mr.Reeはい、私の配列は本当に小さかったです。ありがとう。ブロックコピーの方が優れているかどうかに関心があります...
amalgamate

7

Concatメソッドに注意してください。C#のポスト配列連結では、次のように説明されています。

var z = x.Concat(y).ToArray();

大規模な配列の場合は非効率的です。つまり、このConcatメソッドは中規模のサイズの配列(最大10000要素)専用です。


2
10,000を超える要素を含む配列で何をする必要がありますか?
アレックス、2016

6
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;
}

2
StackOverflowでは、コードを貼り付けるだけでなく、アプローチについても説明してください。この特定のケースでは、あなたの遅い答えがすでに与えられた(そして受け入れられた)答えに何を追加するかも説明する必要があるかもしれません
ガートアーノルド

1
最初のパラメータの前に「this」が何をしているのかはわかりませんが、残りの部分では、これは優れた関数です。ジェネリックで、パラメーターの数は無限です。
Nyerguds 2012

2
こんにちはNyerguds。質問に答えるには、「this」キーワードを使用して関数を拡張メソッドにします。拡張メソッドの詳細については、このMSDNの記事を
JFish222 '31

6

Buffer.BlockCopyover を使用すると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この質問の範囲を超えて型変換のためのいくつかのユーティリティを提供しています。


6

遅い答え:-)。

public static class ArrayExtention
    {

        public static T[] Concatenate<T>(this T[] array1, T[] array2)
        {
            T[] result = new T[array1.Length + array2.Length];
            array1.CopyTo(result, 0);
            array2.CopyTo(result, array1.Length);
            return result;
        }

    }

3

結合された配列を保持するためのRAM(およびCPU)の観点から最も効率的な構造は、IEnumerableを実装する(または配列から派生したい場合でも)特別なクラスであり、値を読み取るために元の配列に内部的にリンクします。AFAIK Concatはまさにそれを行います。

サンプルコードでは、.ToArray()を省略できますが、これにより効率が向上します。


3

古いスレッドを復活させて申し訳ありませんが、これはどうですか:

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>[])に変更することです。

お役に立てれば。


2

あなたはそれをあなたが参照した方法で行うことができます、またはあなたがそれについて本当に手に入れたいならあなたはあなた自身のループをロールすることができます:

        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];

@nawfalそれは配列サイズに依存すると思います。これは私の小さな配列サイズのテストに勝ちました。
合併

2

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のソリューションは少し高速で、ラムダ式が最も低速です。所要時間は配列要素のタイプに依存しますが、何百万もの呼び出しがない限り、メソッド間に大きな違いはありません。


1

覚えておく必要があるのは、LINQを使用するときに遅延実行を利用していることです。ここで説明する他のメソッドはすべて完全に機能しますが、すぐに実行されます。さらに、Concat()関数はおそらく、自分ではできない方法(内部APIの呼び出し、OS呼び出しなど)で最適化されています。とにかく、本当に最適化を試みる必要がない限り、あなたは現在「すべての悪の根源」への道を進んでいます;)


1

以下を試してください:

T[] r1 = new T[size1];
T[] r2 = new T[size2];

List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();

1

これが私の答えです:

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  実際には新しい配列を作成してメモリを占有するため、後続の方法  はそのような利点を打ち消します。新しい配列。
  • @Jodrellが言ったように、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();

後者の方がはるかにエレガントですが、前者の方がパフォーマンスが明らかに優れています。

追加情報については、私のブログのこの投稿を参照しください。


0

int []の場合、あなたがしたことは私には良さそうです。astanderの回答もに有効ですList<int>


2
ConcatはList <int>でも機能します。それがConcatの優れた点であり、すべてのIEnumerable <>で機能します
Mike Two

0

10000要素未満の小さな配列の場合:

using System.Linq;

int firstArray = {5,4,2};
int secondArray = {3,2,1};

int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();

必要がないときになぜLinqを使用するのですか?
伊奈

0
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も使用しないため軽量です。

ソリューションは簡潔であり、一般性が追加されても、実行時のオーバーヘッドが大幅に増えることはありません。


私は新しい質問を見つけることを試みることをお勧めします。または、あなたの質問とほとんど同じようなものを含めて、まだ多数の回答がない帽子を探してください。
Andrew Barber

このソリューションを提案したのは、他のソリューションの優れている点を要約しているからです。細工されました。
drowa 2014年

-2

int [] x = new int [] {1、2、3}; int [] y = new int [] {4、5};

int [] z = x.Union(y).ToArray();


2
UnionDistinct結合されたコレクションから重複を暗黙的に呼び出して削除するため、これを行うにはあまり良い方法ではありません。Concatはるかに良いですが、それは元の質問に既にあります。
nurchi 2017年

-3
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]);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.