我想用LINQ来解决以下问题,我有以下几个集合:
List<byte> byteList = new List<byte() { 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x3, 0x4, 0x02 };此示例中的数据遵循以下模式:
byteList =地址(1,2,3,...n)
byteList1 =旧状态,基本上代表枚举
byteList2 =新状态,同上
我正在与一个嵌入式设备交互,这就是我可以查看输入更改的方式。
为了清理代码并使维护程序员更容易理解我的逻辑,我想抽象出一些涉及的细节,并将每个三字节的数据集提取为一个匿名类型,以便在函数中使用,以执行一些额外的处理。我已经写了一个快速实现,但我相信它可以大大简化。我在试着清理代码,而不是混水摸鱼!必须有一种更简单的方法来完成以下操作:
List<byte> byteList = new List<byte>()
{
0x01, 0x09, 0x01, 0x02, 0x08, 0x02, 0x03, 0x07, 0x03
};
var addresses = byteList
.Where((b, i) => i % 3 == 0)
.ToList();
var oldValues = byteList
.Where((b, i) => i % 3 == 1)
.ToList();
var newValues = byteList
.Where((b, i) => i % 3 == 2)
.ToList();
var completeObjects = addresses
.Select((address, index) => new
{
Address = address,
OldValue = oldValues[index],
NewValue = newValues[index]
})
.ToList();
foreach (var anonType in completeObjects)
{
Console.WriteLine("Address: {0}\nOld Value: {1}\nNew Value: {2}\n",
anonType.Address, anonType.OldValue, anonType.NewValue);
}发布于 2012-03-22 06:15:01
你可以使用Enumerable.Range和一些数学:
List<byte> byteList = new List<byte>()
{
0x01, 0x09, 0x01, 0x02, 0x08, 0x02, 0x03, 0x07, 0x03
};
var completeObjects = Enumerable.Range(0, byteList.Count / 3).Select(index =>
new
{
Address = byteList[index * 3],
OldValue = byteList[index * 3 + 1],
NewValue = byteList[index * 3 + 2],
});如果字节数不是3的倍数,则会忽略多余的一到两个字节。
发布于 2012-03-22 06:07:41
为简化起见,我将创建一个record类型并使用for循环:
class RecordType
{
//constructor to set the properties omitted
public byte Address { get; private set; }
public byte OldValue { get; private set; }
public byte NewValue { get; private set; }
}
IEnumerable<RecordType> Transform(List<byte> bytes)
{
//validation that bytes.Count is divisible by 3 omitted
for (int index = 0; index < bytes.Count; index += 3)
yield return new RecordType(bytes[index], bytes[index + 1], bytes[index + 2]);
}或者,如果您确实需要匿名类型,则可以不使用linq:
for (int index = 0; index < bytes.Count; index += 3)
{
var anon = new { Address = bytes[index], OldValue = bytes[index + 1], NewValue = bytes[index + 3] };
//... do something with anon
}Linq非常有用,但它在这项任务中很笨拙,因为序列项根据它们在序列中的位置具有不同的含义。
发布于 2012-03-22 06:15:04
我不确定这是不是一个聪明的解决方案,但我使用了这个示例来尝试在不创建单独列表的情况下实现这一点。
var completeObjects = byteList
// This is required to access the index, and use integer
// division (to ignore any reminders) to group them into
// sets by three bytes in each.
.Select((value, idx) => new { group = idx / 3, value })
.GroupBy(x => x.group, x => x.value)
// This is just to be able to access them using indices.
.Select(x => x.ToArray())
// This is a superfluous comment.
.Select(x => new {
Address = x[0],
OldValue = x[1],
NewValue = x[2]
})
.ToList();https://stackoverflow.com/questions/9813499
复制相似问题