我有一个如下所示的数据列表
Item Vendor Compliance Status
I1 V1 C1 Y
I1 V1 C2 N
I1 V1 C3 Y
I1 V2 C1 Y
I1 V2 C2 Y
I2 V1 C3 Y
如何查询以使其成为
Item Vendor C1 C2 C3
I1 V1 Y N Y
I1 V2 Y Y -
I2 V1 - - Y
虽然合规性可能有很多,但不一定只有C1,C2,C3。
答案 0 :(得分:2)
我将欺骗@Serv并使用他用于定义数据的部分代码(叹息 - 是的,我很懒惰。)
要处理dynamic
方面的许多合规性,您可以使用ExpandoObject
。您需要做的就是获取所有现有的合规性类型,并为每种类型为您的对象分配属性。
void Main()
{
var content = new List<Content>()
{
new Content("I1", "V1", "C1", true),
new Content("I1", "V1", "C2", false),
new Content("I1", "V1", "C3", true),
new Content("I1", "V2", "C1", true),
new Content("I1", "V2", "C2", true),
new Content("I2", "V1", "C3", true),
new Content("I2", "V1", "C4", true)
};
var compliances = content.Select(c=>c.Compliance).Distinct();
var temp = content.GroupBy (c => new {Item = c.Item, Vendor = c.Vendor});
var results = temp.Select (t =>
{
dynamic result = new ExpandoObject();
result.Item = t.Key.Item;
result.Vendor = t.Key.Vendor;
foreach(var compliance in compliances)
{
var isCompliant = t.Any(x => x.Compliance == compliance && x.Status.GetValueOrDefault());
((IDictionary<String, Object>)result).Add(compliance, isCompliant);
}
return result;
}).Dump();
}
public class Content
{
public Content(string item, string vendor, string compliance, bool? status)
{
Item = item; Vendor = vendor; Compliance = compliance; Status = status;
}
public string Item { get; set; }
public string Vendor { get; set; }
public string Compliance { get; set; }
public bool? Status { get; set; }
}
结果:
修改强>
要在合规性不存在时获取null
而不是false
,请使用此代码foreach
循环:
var isCompliant = t.FirstOrDefault(x => x.Compliance == compliance);
((IDictionary<String, Object>)result).Add(compliance, isCompliant == null ? null : isCompliant.Status);
结果如下:
答案 1 :(得分:1)
我很确定通过这样做违反了十几个良好编程原则,但我认为这个解决方案有效。我所做的是在Linqpad中创建了一个类,其中Status是bool类型(我很懒)。
这是整个片段,因此您可以重现它:
void Main()
{
var content = new List<Content>()
{
new Content("I1", "V1", "C1", true),
new Content("I1", "V1", "C2", false),
new Content("I1", "V1", "C3", true),
new Content("I1", "V2", "C1", true),
new Content("I1", "V2", "C2", true),
new Content("I2", "V1", "C3", true)
};
var temp = content.GroupBy (c => new {Item = c.Item, Vendor = c.Vendor});
var result = temp.Select (t => new
{
Item = t.Key.Item,
Vendor = t.Key.Vendor,
C1 = content.Where(x => x.Item == t.Key.Item && x.Vendor == t.Key.Vendor && x.Compliance == "C1").Select (x => x.Status),
C2 = content.Where(x => x.Item == t.Key.Item && x.Vendor == t.Key.Vendor && x.Compliance == "C2").Select (x => x.Status),
C3 = content.Where(x => x.Item == t.Key.Item && x.Vendor == t.Key.Vendor && x.Compliance == "C3").Select (x => x.Status)
}).Dump();
}
// Define other methods and classes here
public class Content
{
public Content(string item, string vendor, string compliance, bool? status)
{
Item = item; Vendor = vendor; Compliance = compliance; Status = status;
}
public string Item { get; set; }
public string Vendor { get; set; }
public string Compliance { get; set; }
public bool? Status { get; set; }
}
这是输出,可以提供您的预期:
答案 2 :(得分:1)
鉴于您的数据为:
class Data
{
public int Item {get; set;}
public int Vendor {get; set;}
public int Compliance {get; set;}
public bool Status {get; set;}
}
Data[] data =
{
new Data {Item=1, Vendor=1, Compliance=1, Status=true},
new Data {Item=1, Vendor=1, Compliance=2, Status=false},
new Data {Item=1, Vendor=1, Compliance=3, Status=true},
new Data {Item=1, Vendor=2, Compliance=1, Status=true},
new Data {Item=1, Vendor=2, Compliance=2, Status=true},
new Data {Item=2, Vendor=1, Compliance=3, Status=true}
};
可能的解决方案可能
var compliance = data.Select(d => d.Compliance).Distinct().ToList();
var result = data.GroupBy(d => new {d.Item, d.Vendor})
.Select(g => new
{
Item = g.Key.Item,
Vendor = g.Key.Vendor,
Compliance = (from c in compliance
join cs in g.Select(x => new {x.Compliance, x.Status}) on c equals cs.Compliance into j
from cs in j.DefaultIfEmpty()
select new { Compliance = c, Value = cs!=null ? cs.Status : (bool?)null })
});
导致
对于不同Compliance
值的任意数字,您不能使用强类型结果,但可以使用{{1将Join
的结果转换为Dictionary<string, bool?>
方法。