我将这更多地作为学习练习发布,而不是因为我需要将实现更改为强制循环。我的问题是如何将此循环转换为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;
}
答案 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;
}