给出以下接口和两个类:
public static void main(String[] args) {
for(int i=0;i<10;i++){
for(int k=0;k<i;k++){
System.out.print("*");
}
System.out.println();
}
}
并给出了使用它们的以下逻辑:
public interface IMyObj
{
int Id { get; set; }
}
public class MyObj1 : IMyObj
{
public MyObj1(int id) { Id = id; }
public int Id { get; set; }
public override string ToString() => $"{GetType().Name} : {Id}";
}
public class MyObj2 : IMyObj
{
public MyObj2(int id) { Id = id; }
public int Id { get; set; }
public override string ToString() => $"{GetType().Name} : {Id}";
}
测试通过了,我在var numbers = new[] { 1, 5, 11, 17 };
var list = new List<IMyObj>();
foreach (var n in numbers)
{
// I'd like to simplify this part with LINQ...
list.Add(new MyObj1(n));
list.Add(new MyObj2(n));
}
Assert.AreEqual(8, list.Count);
里面看到了我想要的内容 - 每个数字有两个对象实例:
list
我的问题是,如何使用LINQ简化Count = 8
[0]: {MyObj1 : 1}
[1]: {MyObj2 : 1}
[2]: {MyObj1 : 5}
[3]: {MyObj2 : 5}
[4]: {MyObj1 : 11}
[5]: {MyObj2 : 11}
[6]: {MyObj1 : 17}
[7]: {MyObj2 : 17}
循环逻辑?我想也许可能有一种优雅的方式与SelectMany
运算符一样,但我无法生成相同的输出。
答案 0 :(得分:15)
SelectMany
确实是你想要的:
var list = numbers.SelectMany(n => new IMyObj[] { new MyObj1(n), new MyObj2(n) })
.ToList();
换句话说,对于每个数字,创建一个双元素数组,然后使用SelectMany
展平。
new IMyObj[]
部分是必需的而不仅仅是new[]
,因为类型推断无法说明您想要的数组类型。如果类型相同,您可以执行以下操作:
var list = numbers.SelectMany(n => new[] { new MyObj(n), new MyObj(n) })
.ToList();
答案 1 :(得分:0)
您可以使用[Union][1]
连接两个列表:
var result = numbers.Select(x => (IMyObj) new MyObj1(x))
.Union(numbers.Select(x => x => new MyObj2(x)));
另外一个接一个地:
var l1 = numbers.Select(x => new MyObj1(x)).Cast<IMyObject>().ToList();
var l2 = numbers.Select(x => new MyObj(x));
var result = l1.Concat(l2);
或l1.AddRange(l2)
。
当然,所有这些方法都不会与您的inout具有相同的顺序,因为首先存储MyObj1
之外的所有实例,然后存储MyOb2
的所有实例。