应用“Join”方法的最佳方法是什么,一般类似于String.Join(...)的工作方式?

时间:2013-10-25 23:50:06

标签: c# arrays performance linq concatenation

如果我有一个字符串数组,例如:var array = new[] { "the", "cat", "in", "the", "hat" },并且我想在每个单词之间加一个空格,我可以简单地调用String.Join(" ", array)

但是,我说我有一个整数数组数组(就像我可以有一个字符数组数组)。我想将它们组合成一个大型数组(展平它们),但同时在每个数组之间插入一个值。

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可以解决这个问题,但遗憾的是我没有看到任何我需要的东西。

3 个答案:

答案 0 :(得分: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>>,并且不限于列表或数组。请注意,这将在两个空序列之间插入一个单独的序列,但如果需要,可以修改该行为。

答案 1 :(得分: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

答案 2 :(得分: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 }