3

たとえば、文字列配列があり、var array = new[] { "the", "cat", "in", "the", "hat" }各単語の間にスペースを入れてそれらを結合したい場合は、単に呼び出すことができますString.Join(" ", array)

しかし、整数配列の配列があるとします (文字配列の配列を持つことができるのと同じように)。それらを 1 つの大きな配列に結合 (フラット化) したいのですが、同時に各配列の間に値を挿入します。

var arrays = new[] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new { 7, 8, 9 }};

var result = SomeJoin(0, arrays); // result = { 1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9 }

私は何かを書きましたが、それは非常に醜く、より良い、よりクリーンな方法があると確信しています。多分もっと効率的ですか?

var result = new int[arrays.Sum(a => a.Length) + arrays.Length - 1];

int offset = 0;
foreach (var array in arrays)
{
     Buffer.BlockCopy(array, 0, result, offset, b.Length);
     offset += array.Length;

     if (offset < result.Length)
     {
         result[offset++] = 0;
     }
}

おそらくこれが最も効率的ですか?わかりません...もっと良い方法があるかどうかを確認するだけです。おそらくLINQがこれを解決するだろうと思っていましたが、残念ながら私が必要としているものは何もありません。

4

3 に答える 3

5

一般に、次の方法でシーケンスを「結合」できます。

public static IEnumerable<T> Join<T>(T separator, IEnumerable<IEnumerable<T>> items)
{
    var sep = new[] {item};
    var first = items.FirstOrDefault();
    if (first == null)
        return Enumerable.Empty<T>();
    else
        return first.Concat(items.Skip(1).SelectMany(i => sep.Concat(i)));      
}

これはあなたのコードで動作します:

var arrays = new[] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new { 7, 8, 9 }};
var result = Join(0, arrays); // result = { 1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9 }

ここでの利点は、これが任意IEnumerable<IEnumerable<T>>の で機能し、リストや配列に限定されないことです。これにより、2 つの空のシーケンスの間にセパレートが挿入されますが、必要に応じて動作を変更できることに注意してください。

于 2013-10-26T00:11:44.170 に答える
2
public T[] SomeJoin<T>(T a, T[][] arrays){
   return arrays.SelectMany((x,i)=> i == arrays.Length-1 ? x : x.Concat(new[]{a}))
                .ToArray();
}

: を使用しているため、コードはシームレスに動作します。そうしないと、入力コレクションのArrayを取得するためにパフォーマンス コストがいくらか失われる可能性があります。Count

于 2013-10-26T00:00:39.273 に答える
2

これは最も効率的ではないかもしれませんが、非常に拡張可能です:

public static IEnumerable<T> Join<T>(this IEnumerable<IEnumerable<T>> source, T separator)
{
  bool firstTime = true;
  foreach (var collection in source)
  {
    if (!firstTime)
      yield return separator;

    foreach (var value in collection)
      yield return value;

    firstTime = false;
  }
}

...

var arrays = new[] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new[] { 7, 8, 9 }};
var result = arrays.Join(0).ToArray();
//  result = { 1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9 }
于 2013-10-26T00:04:48.060 に答える