【问题标题】:How can I split an array into n parts?如何将数组拆分为 n 个部分?
【发布时间】:2013-09-29 22:27:46
【问题描述】:

我有一个字节列表,我想把这个列表分成更小的部分。

var array = new List<byte> {10, 20, 30, 40, 50, 60};

此列表有 6 个单元格。例如,我想将其拆分为 3 个部分,每个部分包含 2 个字节。

我尝试编写一些 for 循环并使用 2D 数组来实现我的目的,但我不知道这是一种正确的方法。

byte[,] array2D = new byte[window, lst.Count / window];
var current = 0;
for (int i = 0; i < rows; i++)
{
    for (int j = 0; j < cols; j++)
    {
        array2D[i, j] = lst[current++];
    }
}

【问题讨论】:

标签: c# arrays multidimensional-array split


【解决方案1】:

一个不错的方法是创建一个通用/扩展方法来拆分任何数组。这是我的:

/// <summary>
/// Splits an array into several smaller arrays.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array to split.</param>
/// <param name="size">The size of the smaller arrays.</param>
/// <returns>An array containing smaller arrays.</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
    for (var i = 0; i < (float)array.Length / size; i++)
    {
        yield return array.Skip(i * size).Take(size);
    }
}

此外,此解决方案被推迟。然后,只需在您的阵列上调用 Split(size)

var array = new byte[] {10, 20, 30, 40, 50, 60};
var splitArray = array.Split(2);

根据要求,这是一个从数组中获取正方形二维数组的通用/扩展方法:

/// <summary>
/// Splits a given array into a two dimensional arrays of a given size.
/// The given size must be a divisor of the initial array, otherwise the returned value is <c>null</c>,
/// because not all the values will fit into the resulting array.
/// </summary>
/// <param name="array">The array to split.</param>
/// <param name="size">The size to split the array into. The size must be a divisor of the length of the array.</param>
/// <returns>
/// A two dimensional array if the size is a divisor of the length of the initial array, otherwise <c>null</c>.
/// </returns>
public static T[,]? ToSquare2D<T>(this T[] array, int size)
{
    if (array.Length % size != 0) return null;

    var firstDimensionLength = array.Length / size;
    var buffer = new T[firstDimensionLength, size];

    for (var i = 0; i < firstDimensionLength; i++)
    {
        for (var j = 0; j < size; j++)
        {
            buffer[i, j] = array[i * size + j];
        }
    }

    return buffer;
}

玩得开心!

【讨论】:

  • 改变了 OP 所需的数据结构完全。他想要square 2D arrays
  • 并非如此。他的square 2D arrays 是他试图解决问题的一种方法,而不是他想要得到的。使用IEnumerable&lt;IEnumerable&lt;T&gt;&gt; 更加灵活。
  • 当然我会选择IEnumerable stuffList stuff 之类的东西。但这似乎是OP想要的。你不能这么肯定。事实上,如果你用Matrix做一些计算,使用square 2D arrays会更好。
  • 事实上我正在尝试执行一些计算,最好使用matrixsquare 2D arraysamples = reshape(Data,M,N); 是 matlab 中的一个方法,并试图在 c# 中编写相同的方法。它转换数据M*N 矩阵,然后我应该为样本或片段sqrt(sum(samples.*samples)) 执行这个等式。有什么建议吗?也感谢您的回复。
  • 拆分方法看起来是正确的。但是 ToSquare2D 有错误。至少它应该是buffer[i, j] = array[i * size + j];(i * size 而不是 i)如果数组确实包含 size^2 个元素,则此更正代码将起作用,否则将引发 IndexOutOfRangeException,因此需要额外的改进。
【解决方案2】:

使用Linq

public List<List<byte>> SplitToSublists(List<byte> source)
{
    return source
             .Select((x, i) => new { Index = i, Value = x })
             .GroupBy(x => x.Index / 100)
             .Select(x => x.Select(v => v.Value).ToList())
             .ToList();
}

简单地使用它

var sublists = SplitToSublists(lst);

【讨论】:

    【解决方案3】:

    这有列表列表

    array.Select((s,i) => array.Skip(i * 2).Take(2)).Where(a => a.Any())
    

    或者这个有项目列表

    array.SelectMany((s,i) => array.Skip(i * 2).Take(2)).Where(a => a.Any())
    

    【讨论】:

    • 这实际上是正确的答案。只需使用Take()Skip()
    【解决方案4】:

    您可能想尝试一下。

    var bytes = new List<byte>(10000);
    int size = 100;
    var lists = new List<List<byte>>(size);
    for (int i = 0; i < bytes.Count; i += size)
    {
            var list = new List<byte>();
            list.AddRange(bytes.GetRange(i, size));
            lists.Add(list);
    }
    

    【讨论】:

    • 这失败并且超出范围;您需要将“GetRange(i, size)”替换为“GetRange(i, Math.Min(size, bytes.Count - i))”
    【解决方案5】:

    如果您有一个要划分的数组,但通过这个简单的解决方案,您可以将缺少的元素平均分配到各个“块”中:

        public static List<int[]> SplitArrey(int[] arrInput, int nColumn) {
    
        List<int[]> result = new List<int[]>(nColumn);
    
        int itemsForColum = arrInput.Length / nColumn;  
        int countSpareElement = arrInput.Length - (itemsForColum * nColumn);    
    
        // Add and extra space for the spare element
        int[] newColumLenght = new int[nColumn];
        for (int i = 0; i < nColumn; i++)
        {
            int addOne = (i < countSpareElement) ? 1 : 0;
            newColumLenght[i] = itemsForColum + addOne;
            result.Add(new int[itemsForColum + addOne]);
        }
    
        // Copy the values
        int offset = 0;
        for (int i = 0; i < nColumn; i++)
        {
            int count_items_to_copy = newColumLenght[i];
            Array.Copy(arrInput, offset, result[i], 0, count_items_to_copy);
            offset += newColumLenght[i];
        }
        return result;
    }
    

    然后:

    int[] arrInput = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
    var result = SplitArrey(arrInput, 5);
    foreach (var item in result) {
     Console.WriteLine("   {0}", String.Join(" ", item));
    }
    

    结果是:

    1 2 3 
    4 5 6 
    7 8 
    9 10 
    11 12
    

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 2012-01-01
      • 2013-03-12
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多