从 IEnumerable 返回数据
Returning data from a IEnumerable
考虑一下,
public class Obj
{
public string PropertyName;
public string Name;
public int Id;
public int Value;
}
List<Obj> lsObjdata = new List<Obj>();
var obj = new Obj { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
lsObjdata.Add(obj);
obj = new Obj { Name = "abc", PropertyName = "Volume", Id= 1, Value = 23};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Oil", Id =1, Value = 45};
lsObjdata.Add(obj);
IEnumerable<IGrouping<String, obj>> results = lsObjData.GroupBy( m => m.Id);
现在,我的 results
将有 3 个相同的值 id.My 业务要求我优先考虑具有 xyz
作为名称的对象,如果它们的属性则忽略另一个匹配。但是,如果 xyz
没有 abc
有的 属性?获取 属性 的 value.Like 上面给出的第三个对象的初始化。
obj = new {Name = "abc", PropertyName = "Oil", Id =1, Value = 45}
此 属性 和名称不存在 xyz
。这应该添加到我的最终输出中。我的结果应该在列表中包含以下两个对象。
obj = new {Name = "abc", PropertyName = "Oil", Id =1, Value = 45}
obj = new { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
PS: 我已经完成了解决方案。
但是,我无法使用 Linq/Lambda 表达式并在单个 line/stroke 中获得解决方案。
任何人都可以在这方面帮助我吗?
谢谢,
山姆
您需要按两个属性进行分组 - Id, PropertyName
然后 select 第一个对象,方法是像这样对分组数据进行排序:-
var results = lsobjdata.GroupBy(x => new { x.Id, x.PropertyName })
.Select(x => x.OrderByDescending(z => z.Name).FirstOrDefault());
这是带有一些示例数据的 Working Fiddle。
因为你没有提到你想要每个结果集中的第一个。我正在提供替代解决方案。
// Define other methods and classes here
public class Obj
{
public string PropertyName;
public string Name;
public int Id;
public int Value;
}
public class Key
{
public string PropertyName;
public int Id;
public override bool Equals(object obj)
{
Key item = obj as Key;
return item.Id == this.Id && item.PropertyName == this.PropertyName;
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + Id.GetHashCode();
hash = (hash * 7) + PropertyName.GetHashCode();
return hash;
}
}
void static Main()
{
List<Obj> lsObjdata = new List<Obj>();
HashSet<Key> keys = new HashSet<Key>();
var obj = new Obj { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
lsObjdata.Add(obj);
obj = new Obj { Name = "abc", PropertyName = "Volume", Id= 1, Value = 23};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Oil", Id =1, Value = 45};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Gas", Id =1, Value = 45};
lsObjdata.Add(obj);
obj = new Obj {Name = "edf", PropertyName = "Gas", Id =1, Value = 45};
lsObjdata.Add(obj);
var results = lsObjdata.GroupBy(m => new Key { Id = m.Id, PropertyName = m.PropertyName })
.Select<IGrouping<Key,Obj>,IEnumerable<Obj>>(x =>
{
if (x.Any(v => v.Name == "xyz") && !keys.Contains(x.Key))
{
return new Obj[]{x.First(v => v.Name == "xyz")};
}
else if (!keys.Contains(x.Key as Key))
{
return x.Select(v=>v);
}
else
return null;
})
.SelectMany(x=>x)
.Where(x=> x != null);
foreach (var res in results)
{
Console.WriteLine(res.PropertyName + " "+res.Name+" "+res.Id+" "+ res.Value);
}
Console.WriteLine(results);
}
考虑一下,
public class Obj
{
public string PropertyName;
public string Name;
public int Id;
public int Value;
}
List<Obj> lsObjdata = new List<Obj>();
var obj = new Obj { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
lsObjdata.Add(obj);
obj = new Obj { Name = "abc", PropertyName = "Volume", Id= 1, Value = 23};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Oil", Id =1, Value = 45};
lsObjdata.Add(obj);
IEnumerable<IGrouping<String, obj>> results = lsObjData.GroupBy( m => m.Id);
现在,我的 results
将有 3 个相同的值 id.My 业务要求我优先考虑具有 xyz
作为名称的对象,如果它们的属性则忽略另一个匹配。但是,如果 xyz
没有 abc
有的 属性?获取 属性 的 value.Like 上面给出的第三个对象的初始化。
obj = new {Name = "abc", PropertyName = "Oil", Id =1, Value = 45}
此 属性 和名称不存在 xyz
。这应该添加到我的最终输出中。我的结果应该在列表中包含以下两个对象。
obj = new {Name = "abc", PropertyName = "Oil", Id =1, Value = 45}
obj = new { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
PS: 我已经完成了解决方案。 但是,我无法使用 Linq/Lambda 表达式并在单个 line/stroke 中获得解决方案。 任何人都可以在这方面帮助我吗? 谢谢, 山姆
您需要按两个属性进行分组 - Id, PropertyName
然后 select 第一个对象,方法是像这样对分组数据进行排序:-
var results = lsobjdata.GroupBy(x => new { x.Id, x.PropertyName })
.Select(x => x.OrderByDescending(z => z.Name).FirstOrDefault());
这是带有一些示例数据的 Working Fiddle。
因为你没有提到你想要每个结果集中的第一个。我正在提供替代解决方案。
// Define other methods and classes here
public class Obj
{
public string PropertyName;
public string Name;
public int Id;
public int Value;
}
public class Key
{
public string PropertyName;
public int Id;
public override bool Equals(object obj)
{
Key item = obj as Key;
return item.Id == this.Id && item.PropertyName == this.PropertyName;
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + Id.GetHashCode();
hash = (hash * 7) + PropertyName.GetHashCode();
return hash;
}
}
void static Main()
{
List<Obj> lsObjdata = new List<Obj>();
HashSet<Key> keys = new HashSet<Key>();
var obj = new Obj { Name = "xyz", PropertyName = "Volume", Id= 1, Value = 25};
lsObjdata.Add(obj);
obj = new Obj { Name = "abc", PropertyName = "Volume", Id= 1, Value = 23};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Oil", Id =1, Value = 45};
lsObjdata.Add(obj);
obj = new Obj {Name = "abc", PropertyName = "Gas", Id =1, Value = 45};
lsObjdata.Add(obj);
obj = new Obj {Name = "edf", PropertyName = "Gas", Id =1, Value = 45};
lsObjdata.Add(obj);
var results = lsObjdata.GroupBy(m => new Key { Id = m.Id, PropertyName = m.PropertyName })
.Select<IGrouping<Key,Obj>,IEnumerable<Obj>>(x =>
{
if (x.Any(v => v.Name == "xyz") && !keys.Contains(x.Key))
{
return new Obj[]{x.First(v => v.Name == "xyz")};
}
else if (!keys.Contains(x.Key as Key))
{
return x.Select(v=>v);
}
else
return null;
})
.SelectMany(x=>x)
.Where(x=> x != null);
foreach (var res in results)
{
Console.WriteLine(res.PropertyName + " "+res.Name+" "+res.Id+" "+ res.Value);
}
Console.WriteLine(results);
}