【问题标题】:How to Divide an array on c#?如何在 C# 上划分数组?
【发布时间】:2015-04-14 15:54:45
【问题描述】:

我必须做一个程序来读取和成像并将其放入字节数组中

var Imagenoriginal = File.ReadAllBytes("10M.bmp");

并将该字节数组划分为 3 个不同的数组,以便将每个新数组发送到其他计算机(使用管道)以在那里处理它们,最后将它们带回原始计算机并最终给出结果。 但我的问题是,如果选择的图像可以具有不同的大小,我该如何做一个能够将字节数组划分为三个不同字节数组的算法。 感谢您的帮助,祝您有美好的一天。 =)

【问题讨论】:

  • 数组的大小是差不多相等,还是可以不同?
  • 或多或少等于 =)
  • buffer.Length / 3 ?稍微注意剩余的字节。聪明的做法当然是不使用 ReadAllBytes() 而是使用 ReadBytes(offset, length) 。
  • 以及如何做到这一点 一点关心 =/
  • 旁注,但你确定你可以这样划分位图吗?那是一个有结构的文件:里面有一个标题、扫描线和像素。如果没有标头,其他进程可以用损坏的扫描线或像素做什么?

标签: c# arrays multiprocessing


【解决方案1】:

你可以划分数组的长度,所以你有三个整数n1n2n3,它们的总和为array.Length。那么,这个使用 LINQ 的 sn-p 应该会有所帮助:

var arr1 = sourceArray.Take(n1).ToArray();
var arr2 = sourceArray.Skip(n1).Take(n2).ToArray();
var arr3 = sourceArray.Skip(n1+n2).Take(n3).ToArray();

现在,在arr1arr2arr3 中,您将拥有源数组的三个部分。你需要使用LINQ,所以在代码的开头不要忘记using System.Linq;

【讨论】:

  • 别忘了.ToArray()
  • @HenkHolterman 哦,天哪。我已经很久没有使用数组了,并且如实说我忘记了 LINQ 返回 IEnumerable 或类似的东西。已解决,谢谢。
【解决方案2】:

你可以这样试试:

public static IEnumerable<IEnumerable<T>> DivideArray<T>(this T[] array, int size)
{
    for (var i = 0; i < (float)array.Length / size; i++)
    {
        yield return array.Skip(i * size).Take(size);
    }
}

这样的调用:

var arr = new byte[] {1, 2, 3, 4, 5,6};
var dividedArray = arr.DivideArray(3);

这是一种 LINQ 方法:

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

【讨论】:

  • 它会起作用,但它看起来不像你想要扩大的东西。
  • 在调用第二个DivideArray 后,您需要在结果上调用ToArray(),因为它返回一个List
【解决方案3】:

您是否考虑过使用Streams?您可以扩展 Stream 类以提供所需的行为,如下所示:

public static class Utilities
{
    public static IEnumerable<byte[]> ReadBytes(this Stream input, long bufferSize)
    {
        byte[] buffer = new byte[bufferSize];
        int read;

        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            using (MemoryStream tempStream = new MemoryStream())
            {
                tempStream.Write(buffer, 0, read);
                yield return tempStream.ToArray();
            }            
        }
    }

    public static IEnumerable<byte[]> ReadBlocks(this Stream input, int nblocks)
    {
        long bufferSize = (long)Math.Ceiling((double)input.Length / nblocks);
        return input.ReadBytes(bufferSize);
    }
}
  • ReadBytes 扩展方法读取input 流并使用指定的bufferSize 将其数据作为字节数组序列返回。

  • ReadBlocks 扩展方法以适当的缓冲区大小调用ReadBytes,以便序列中的元素数等于nblocks

然后您可以使用ReadBlocks 来实现您想要的:

public class Program
{
    static void Main()
    {
        FileStream inputStream = File.Open(@"E:\10M.bmp", FileMode.Open);
        const int nblocks = 3;

        foreach (byte[] block in inputStream.ReadBlocks(nblocks))
        {
            Console.WriteLine("{0} bytes", block.Length);
        }
    }
}

注意ReadBytes 如何使用tempStreamread 将从输入流 读取的字节写入内存,然后再将它们转换为字节数组,它解决了剩余字节在 cmets 中提到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2017-06-30
    相关资源
    最近更新 更多