Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何巧妙地从IEnumerable创建匿名类型<;T>;?_C#_.net_Linq_Collections - Fatal编程技术网

C# 如何巧妙地从IEnumerable创建匿名类型<;T>;?

C# 如何巧妙地从IEnumerable创建匿名类型<;T>;?,c#,.net,linq,collections,C#,.net,Linq,Collections,我想使用LINQ解决以下问题,我有以下收集: List<byte> byteList = new List<byte() { 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x3, 0x4, 0x02 }; List byteList=新列表i%3==0) .ToList(); var oldValues=byteList 。式中((b,i)=>i%3==1) .ToList(); var newValues=byteList 。式中((b,i)=>

我想使用LINQ解决以下问题,我有以下收集:

List<byte> byteList = new List<byte() { 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x3, 0x4, 0x02 };
List byteList=新列表i%3==0)
.ToList();
var oldValues=byteList
。式中((b,i)=>i%3==1)
.ToList();
var newValues=byteList
。式中((b,i)=>i%3==2)
.ToList();
var completeObjects=地址
.选择((地址、索引)=>新建
{ 
地址,
OldValue=oldValues[索引],
NewValue=newValues[索引]
})
.ToList();
foreach(completeObjects中的var anonType)
{
WriteLine(“地址:{0}\n旧值:{1}\n新值:{2}\n”,
anonType.Address、anonType.OldValue、anonType.NewValue);
}

为了简化,我将创建一个记录类型,并使用一个
循环:

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]);
}
类记录类型
{
//构造函数来设置省略的属性
公共字节地址{get;private set;}
公共字节OldValue{get;private set;}
公共字节NewValue{get;private set;}
}
IEnumerable转换(列表字节)
{
//验证bytes.Count是否可被3整除
对于(int index=0;index
或者,如果您确实需要匿名类型,则可以不使用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
}
for(int index=0;index

Linq非常有用,但在执行此任务时会很尴尬,因为序列项根据其在序列中的位置而具有不同的含义。

您可以使用
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],
    });
List byteList=new List()
{
0x01、0x09、0x01、0x02、0x08、0x02、0x03、0x07、0x03
};
var completeObjects=Enumerable.Range(0,byteList.Count/3)。选择(索引=>
新的
{
地址=字节列表[索引*3],
OldValue=字节列表[索引*3+1],
NewValue=byteList[索引*3+2],
});

如果字节数不是3的倍数,那么多余的一个或两个字节将被忽略。

我不确定这是否是一个聪明的解决方案,但我使用了这个示例尝试在不创建单独列表的情况下实现这一点

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();
如果您必须使用LINQ(不确定这是一个好的计划),那么一个选项是:

using System;
using System.Collections.Generic;
using System.Linq;

static class LinqExtensions
{
    public static IEnumerable<T> EveryNth<T>(this IEnumerable<T> e, int start, int n)
    {
        int index = 0;
        foreach(T t in e)
        {
            if((index - start) % n == 0)
            {
                yield return t;
            }
            ++index;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        List<byte> byteList = new List<byte>()
        {
            0x01, 0x09, 0x01, 0x02, 0x08, 0x02, 0x03, 0x07, 0x03
        };

        var completeObjects =
            byteList.EveryNth(0, 3).Zip
            (
                byteList.EveryNth(1, 3).Zip
                (
                    byteList.EveryNth(2, 3),
                    Tuple.Create
                ),
                (f,t) => new { Address = f, OldValue = t.Item1, NewValue = t.Item2 }
            );

        foreach (var anonType in completeObjects)
        {
            Console.WriteLine("Address: {0}\nOld Value: {1}\nNew Value: {2}\n", anonType.Address, anonType.OldValue, anonType.NewValue);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
静态类LinqExtensions
{
公共静态IEnumerable EveryNth(此IEnumerable e,int start,int n)
{
int指数=0;
foreach(T在e中)
{
如果((索引-开始)%n==0)
{
收益率t;
}
++指数;
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{
List byteList=新列表()
{
0x01、0x09、0x01、0x02、0x08、0x02、0x03、0x07、0x03
};
变量completeObjects=
byteList.EveryNth(0,3).Zip
(
byteList.EveryNth(1,3).Zip
(
byteList.EveryNth(2,3),
Tuple.Create
),
(f,t)=>new{Address=f,OldValue=t.Item1,NewValue=t.Item2}
);
foreach(completeObjects中的var anonType)
{
Console.WriteLine(“地址:{0}\n旧值:{1}\n新值:{2}\n”,anonType.Address,anonType.OldValue,anonType.NewValue);
}
}
}
这个怎么样

var addresses = 
    from i in Enumerable.Range(0, byteList.Count / 3)
    let startIndex = i * 3
    select new
    {
        Address = byteList[startIndex],
        OldValue = byteList[startIndex + 1],
        NewValue = byteList[startIndex + 2]
    };

注意:我独立于Michael Liu的答案得出了这个结论,虽然他的答案实际上是相同的,但我将把这个答案留在这里,因为它看起来更漂亮。:-)

这里尝试使用扩展方法
ChunkToList
IEnumerable
拆分为
IList
的块

用法:

        var compObjs = byteList.ChunkToList(3)
                               .Select(arr => new { 
                                       Address  = arr[0],
                                       OldValue = arr[1],
                                       NewValue = arr[2] 
                               });
实施:

static class LinqExtensions
{
    public static IEnumerable<IList<T>> ChunkToList<T>(this IEnumerable<T> list, int size)
    {
        Debug.Assert(list.Count() % size == 0);

        int index = 0;
        while (index < list.Count())
        {
            yield return list.Skip(index).Take(size).ToList();
            index += size;
        }
    }
}
静态类LinqExtensions
{
公共静态IEnumerable ChunkToList(此IEnumerable列表,整数大小)
{
Assert(list.Count()%size==0);
int指数=0;
while(索引
对于非负i,
(i+2)%3==0
相当于
i%3==1
。我不确定LINQ在这方面有多大帮助。MoreLINQ包括
Batch()
方法,这是一种将可枚举数据分块到大小合适的存储桶中的好方法。或者,一个简单的
for
循环可能会非常简单和清晰。嗯,
splitintosf
会是一个更好的名称,不是吗:
byteList.splitintosf(3)。选择
…我非常喜欢您的解决方案适用于可枚举且相当干净的事实。非常有趣的解决问题的方法,谢谢你给我展示了另一种完成工作的方法。这是一个优秀、简洁的答案,正是我想要的类型。不幸的是,与查询语法相比,我更喜欢使用LINQ的方法语法。也许我对python的体验已经展现出来了,但感觉更自然。谢谢你给我另一种方法来完成这项工作!这似乎是使用LINQ解决我的问题的最干净的方法。我知道LINQ可能不是解决此问题的最佳方法,但问题确实指定使用LINQ。这个问题是作为一个学习工具,我的产品代码可能会使用phoog解决方案的变体。我承认这是我收到的最实用、最容易维护的答案。您的答案可能会有变化,这可能是我为产品代码选择的路线,但由于问题指定了LINQ,我需要公平对待那些记住我的问题框架的人。谢谢你的回答。@Nate很公平;不知怎的,我忘记了“我想用”这个短语
static class LinqExtensions
{
    public static IEnumerable<IList<T>> ChunkToList<T>(this IEnumerable<T> list, int size)
    {
        Debug.Assert(list.Count() % size == 0);

        int index = 0;
        while (index < list.Count())
        {
            yield return list.Skip(index).Take(size).ToList();
            index += size;
        }
    }
}