如何从IEnumerable中删除块?

时间:2014-07-17 22:39:28

标签: c# linq

我将这更多地作为学习练习发布,而不是因为我需要将实现更改为强制循环。我的问题是如何将此循环转换为LINQ?给定输入的IEnumerable字节,其被认为是8字节的“块”。输出IEnumerable应该包含任何包含0的块。

粗略的势在必行的实施

    private static IEnumerable<byte> StripBlocksWithZeroes(IEnumerable<byte> input)
    {
        var stripped = new List<byte>();
        var inputArray = input.ToArray();
        for (int i = 0; i < inputArray.Length; i += 8)
        {
            if (inputArray[i + 0] != 0 &&
                inputArray[i + 1] != 0 &&
                inputArray[i + 2] != 0 &&
                inputArray[i + 3] != 0 &&
                inputArray[i + 4] != 0 &&
                inputArray[i + 5] != 0 &&
                inputArray[i + 6] != 0 &&
                inputArray[i + 7] != 0)
            {
                stripped.Add(inputArray[i + 0]);
                stripped.Add(inputArray[i + 1]);
                stripped.Add(inputArray[i + 2]);
                stripped.Add(inputArray[i + 3]);
                stripped.Add(inputArray[i + 4]);
                stripped.Add(inputArray[i + 5]);
                stripped.Add(inputArray[i + 6]);
                stripped.Add(inputArray[i + 7]);
            }
        }
        return stripped;
    }

3 个答案:

答案 0 :(得分:4)

脱离我的头顶:

inputArray.Select((item, index) => new {item, groupIndex = index / 8})
          .GroupBy(x => x.groupIndex)
          .Where(g => g.All(x => x.item != 0))
          //.Select(g => g.First().item)
          .SelectMany(g => g.Select(x => x.item))

一点解释:

使用groupIndex标记每个项目,利用整数除法,因此每个连续的8个组将具有相同的groupIndex。

按组索引分组,现在我们有一系列序列。

对于每个内部序列,请确保它不包含零。

将得到的序列序列展平为单个序列。

答案 1 :(得分:3)

又一个略有不同的版本:

    return input.Select((value, index) => new { value, index })
                .GroupBy(x => x.index / 8, x => x.value)
                .Where(g => g.All(value => value != 0))
                .SelectMany(g => g);

兴趣点:此代码使用this GroupBy overload,它使元素选择器尽快摆脱索引。

答案 2 :(得分:2)

你可以使用&#34;整数除法技巧&#34;分组8个字节并检查它们是否为0:

private static IEnumerable<byte> StripBlocksWithZeroes(IEnumerable<byte> input)
{
    IEnumerable<byte> stripped = input
        .Select((b, i) => new { Byte = b, Index = i })
        .GroupBy(x => x.Index / 8)
        .Where(g => g.All(x => x.Byte != 0))
        .SelectMany(g => g.Select(x => x.Byte))
        .ToList();
    return stripped;
}