我需要合并2个对象列表,它们共享相同的接口,但具有不同的具体类。
结果应包含一个基于每个具体类的新对象列表,并基于列表中相同对象的比较为每个对象设置属性。
class Program
{
static void Main(string[] args)
{
List<IStuff> stuffList1 = new List<IStuff>();
List<IStuff> stuffList2 = new List<IStuff>();
stuffList1.Add(new Toaster
{
ValueOfMyThing = 1
});
stuffList1.Add(new Car
{
ValueOfMyThing = 3
});
stuffList1.Add(new Onion
{
ValueOfMyThing = 3
});
stuffList2.Add(new Toaster
{
ValueOfMyThing = 2
});
stuffList2.Add(new Car
{
ValueOfMyThing = 1
});
stuffList2.Add(new Onion
{
ValueOfMyThing = 5
});
List<IStuff> stuffList3 = new List<IStuff>();
// Need to merge stuffList1 and stuffList2 taking the stuff that has the higher valueOfMyThing
// The result should be a stuffList3 with a Toaster 2 a Car 3 and an Onion 5
}
}
interface IStuff
{
int ValueOfMyThing { get; set; }
}
class Toaster: IStuff
{
public int ValueOfMyThing { get; set; }
}
class Car : IStuff
{
public int ValueOfMyThing { get; set; }
}
class Onion : IStuff
{
public int ValueOfMyThing { get; set; }
}
答案 0 :(得分:4)
首先,您需要接口中的common属性,否则当您枚举List<IStuff>
中的项目时,您不能使用多态性来访问它:
interface IStuff
{
int ValueOfMyThing { get; set; }
}
现在也将此属性添加到类中(省略)。
然后,您可以使用此LINQ查询对具体类型进行分组,例如Car
,并为每个组获取最高ValueOfMyThing
的项目:
List<IStuff> stuffList3 = stuffList1.Concat(stuffList2)
.GroupBy(x => x.GetType())
.Select(g => g.OrderByDescending(x => x.ValueOfMyThing).First())
.ToList();
这可行,但是我需要stuffList3包含新的实例
然后,您可以提供一种将现有实例复制到新实例的方法:
public interface IStuff
{
int ValueOfMyThing { get; set; }
IStuff Copy();
}
将其添加到您的班级中:
public class Toaster : IStuff
{
public int ValueOfMyThing { get; set; }
public IStuff Copy()
{
return new Toaster { ValueOfMyThing = ValueOfMyThing };
}
}
// ...
并致电Copy
:
List<IStuff> stuffList3 = stuffList1.Concat(stuffList2)
.GroupBy(x => x.GetType())
.Select(g => g.OrderByDescending(x => x.ValueOfMyThing).First().Copy())
.ToList();
答案 1 :(得分:0)
第一,您需要让valueOfMyThing
接口中的IStuff
属性或字段成为类的合同。
interface IStuff
{
int valueOfMyThing { get; set; }
}
class Toaster : IStuff
{
public int valueOfMyThing { get; set; }
}
class Car : IStuff
{
public int valueOfMyThing { get; set; }
}
class Onion : IStuff
{
public int valueOfMyThing { get; set; }
}
然后添加此扩展方法以允许使用lambda参数进行独特查询:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this
IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (var element in source)
{
if (keySelector != null && seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
最后在列表中使用它。
List<IStuff> stuffList3 = new List<IStuff>();
stuffList3.AddRange(stuffList2);
stuffList3.AddRange(stuffList1);
var r = stuffList3.DistinctBy(x => x.valueOfMyThing);
答案 2 :(得分:0)
我需要创建对象的新实例。所以我最终这样做: 首先是Tim Schmelmer提到的:
interface IStuff
{
int ValueOfMyThing { get; set; }
}
class Toaster: IStuff
{
public int ValueOfMyThing { get; set; }
}
class Car : IStuff
{
public int ValueOfMyThing { get; set; }
}
class Onion : IStuff
{
public int ValueOfMyThing { get; set; }
}
然后根据此答案Merge two Lists of different types
List<IStuff> stuffList3 = new List<IStuff>();
var joinedData = stuffList1.Join(stuffList2, sl1 => sl1.GetType(), sl2 => sl2.GetType(), (sl1, sl2) => new { sl1, sl2 });
foreach (var pair in joinedData)
{
var newStuffValue = Math.Max(pair.sl1.ValueOfMyThing, pair.sl2.ValueOfMyThing);
var newStuff = (IStuff)Activator.CreateInstance(pair.sl1.GetType());
newStuff.ValueOfMyThing = newStuffValue;
stuffList3.Add(newStuff);
}
现在我有了一个新的具体课程列表,但是我不确定这是最好的方法