gpt4 book ai didi

c# - 使用 LINQ 和匿名类型进行透视?

转载 作者:行者123 更新时间:2023-11-30 22:09:46 25 4
gpt4 key购买 nike

我已经搜索了其他“linq pivot”问题,但我似乎无法找到与我的完全匹配的问题。我需要对所有匿名类型执行此操作。我正在尝试使用如下数据跟踪支票交易

Check# - Step - Amount

100 - Book - 100

100 - Bank - 100

100 - Account - 100

101 - Book - 75

101 - Bank - 75

101 - Account - NULL

作为匿名类型,我再次寻找的结果是:

Check # Book   - Bank   - Account 

100 - 100 - 100- 100

101 - 75 - 75 - NULL

我真的不知道我是否需要先进行分组(通过检查#)。我需要它是匿名的,因为我不知道此处显示的步骤的名称。有时会有 3 个步骤,有时会有更多。

最佳答案

我做过类似的事情。匿名类型不起作用,因为我必须动态地处理列,并且匿名类型仍然必须在编译时是已知的。 ExpandoObject但是,它允许我们在运行时定义属性。

我已经做了一个快速控制台应用程序作为证明:

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

class Program
{
static void Main(string[] args)
{
List<Record> input = new List<Record>();
input.Add(new Record { CheckNumber = 100, Step = "Book", Amount = 100 });
input.Add(new Record { CheckNumber = 100, Step = "Bank", Amount = 100 });
input.Add(new Record { CheckNumber = 100, Step = "Account", Amount = 100 });
input.Add(new Record { CheckNumber = 101, Step = "Book", Amount = 75 });
input.Add(new Record { CheckNumber = 101, Step = "Bank", Amount = 75 });
List<ExpandoObject> results = GetPivotRows(input);

//test
for (int i = 0; i < results.Count; i++)
{
dynamic record = results[i];
Console.WriteLine("{0} - {1} - {2} - {3}", record.CheckNumber, record.Book, record.Bank, record.Account);
}
}

public static List<ExpandoObject> GetPivotRows(List<Record> input)
{
List<string> steps = input.Select(e => e.Step).Distinct().ToList();
Dictionary<int, ExpandoObject> outputMap = new Dictionary<int,ExpandoObject>();
for (int i = 0; i < input.Count; i++)
{
dynamic row;
if(outputMap.ContainsKey(input[i].CheckNumber))
{
row = outputMap[input[i].CheckNumber];
}
else
{
row = new ExpandoObject();
row.CheckNumber = input[i].CheckNumber;
outputMap.Add(input[i].CheckNumber, row);

// Here we're initializing all the possible "Step" columns
for (int j = 0; j < steps.Count; j++)
{
(row as IDictionary<string, object>)[steps[j]] = new Nullable<int>();
}
}

(row as IDictionary<string, object>)[input[i].Step] = input[i].Amount;
}

return outputMap.Values.OrderBy(e => ((dynamic)e).CheckNumber).ToList();
}
}

public class Record
{
public int CheckNumber { get; set; }

public string Step { get; set; }

public decimal Amount { get; set; }
}

输出:

100 - 100 - 100- 100

101 - 75 - 75 -

您可以使用反射来检查过程中创建的实际属性。

编辑:稍微揭开这一点的神秘面纱——如果我将主程序中的“测试”循环更改为:

for (int i = 0; i < results.Count; i++)
{
Console.WriteLine(string.Join(" - ", results[i]));
}

我得到:

[CheckNumber, 100] - [Book, 100] - [Bank, 100] - [Account, 100]
[CheckNumber, 101] - [Book, 75] - [Bank, 75] - [Account, ]

ExpandoObject工具 IDictionary<string, object>在幕后存储它需要的任何东西,同时实现 IDynamicMetaObjectProvider并使用动态绑定(bind)。

关于c# - 使用 LINQ 和匿名类型进行透视?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21342507/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com