以下循环是否有C#LINQ替代方案?

以下循环是否有C#LINQ替代方案?,c#,linq,C#,Linq,假设Foo有一个Bar类型的公共字段“Child”,我有一个给定大小的Foo列表,我有一个相同大小的Bar列表 是否有更有效的方法通过使用Linq而不是提供的代码片段来将孩子分配给父母 for (int i = 0; i < parents.Count; i++) { parents[i].Child = children[i]; } for(int i=0;inew { //选择您计划在这种情况下使用的Foo和Bar属性 日期=食物日期, FooId=foo.Id, FooNam

假设Foo有一个Bar类型的公共字段“Child”,我有一个给定大小的Foo列表,我有一个相同大小的Bar列表

是否有更有效的方法通过使用Linq而不是提供的代码片段来将孩子分配给父母

for (int i = 0; i < parents.Count; i++)
{
   parents[i].Child = children[i];
}
for(int i=0;i
您的
for
循环访问每个父循环一次,因此在大O表示法中为O(n)

如果必须访问每个元素,则无法获得比O(n)更好的结果

我的结论是,没有比这更有效的方法了

你必须这么做吗?
如果
parents[i].Child==children[i]
那么你根本不需要做这个作业,只要转到
子[i]
就可以了,如果你想要一个
父[i]

的孩子,首先:使用LINQ,你不应该试图更改源代码。LINQ旨在将序列中的数据提取到新序列中

因此,在您的问题中,每个Foo都有一个由相同索引标识的条。在数据库术语中,您可以说这种一对一关系是通过为元素提供相同的主键值来实现的

你会问这是否更有效。答案取决于您在创建“Foo列表,每个Foo都有一个且唯一的条”后将如何使用它

如果您想通过添加Foo的条来更改所有原始Foo,那么不,它不会比这更有效

但是,如果您只使用部分结果:只使用一些foo,或者只使用foo和条形图的某些属性,或者有时您希望将其与某些属性一起使用,而有时使用其他属性一起使用,那么最好考虑LINQ:尽可能长时间地保持所有内容
IEnumerable
。这样,如果您执行其他LINQ操作,如FirstOrDefault、Any、Select、GroupBy等,您就不会在完整的列表中填入您无论如何都不会使用的项

正确的LINQ方法在一定程度上取决于您将如何使用它:您是否只在这个特定的过程中使用它?或者您会更频繁地在
Foos
栏中使用此选项吗?也许你还有其他基于索引的一对一关系

我只想在这个过程中使用它 所以你有两个列表,大小相等,而Bar[12]是Foo[12]中唯一的一个

每当你有两个相等长度的x和y序列,并且你想组合{x(0),y(0)},{x,y}等时,考虑使用

的重载之一。 您将只有枚举的Foo[0]和Bar[0]

或者假设您只想在页面中显示它:

int pageSize = 24,
int pageNr = 3;
var pageOfFoosAndBars = foosWithTheirBars.Skip(pageNr * pageSize)
    .Take(pageSize)
    .ToList();
我计划在几个程序中使用Foos和bar来实现这一点 考虑为Foos和bar创建一个扩展方法。这样,您就可以像使用标准LINQ方法一样使用它。如果您不熟悉扩展方法。见:

公共静态IEnumerable组合(此IEnumerable foos,
数不清的酒吧,
Func结果选择器)
{
返回foos.Zip(bar,resultSelector(foo,bar));
}
用法:

IEnumerable<Foo> foos = GetMyFoos();
IEnumerable<Bar> bars = GetBars();

var result = foos.Combine(bars, (foo, bar) => new
{
    // select the Foo and Bar properties that you plan to use in this situation
    Date = foo.Date,
    FooId = foo.Id,
    FooName = foo.Name,

    BarName = bar.Name,
    ...
})
.Where(combineResult => combineResult.Date.Year < 2000)
.GroupBy(foo => foo.Name)
.Select(...);
IEnumerable foos=GetMyFoos();
IEnumerable bar=getbar();
var result=foos.Combine(条,(foo,条)=>new
{
//选择您计划在这种情况下使用的Foo和Bar属性
日期=食物日期,
FooId=foo.Id,
FooName=foo.Name,
BarName=bar.Name,
...
})
.其中(combineResult=>combineResult.Date.Year<2000)
.GroupBy(foo=>foo.Name)
。选择(…);
不,我想用任何序列 在这种情况下,只需使用Zip:

IEnumerable<Student> students = ...
IEnumerable<Address> addresses = ...

var studentsWithTheirAddress = students.Zip(addresses, (student, address) => new
{
    Id = student.Id,
    Name = student.Name,
    Street = address.Street,
    City = address.City,
    ...
})
IEnumerable学生=。。。
IEnumerable地址=。。。
var studentsWithTheirAddress=students.Zip(地址,(学生,地址)=>新建
{
Id=student.Id,
Name=student.Name,
街道=地址。街道,
城市=地址。城市,
...
})

If
parents[i].Child=children[i]那么就不需要分配了,这非常有效:)以什么方式“更有效”?就CPU周期而言,您的方法很好,而且效率肯定不会低于任何LINQ方法。如果您想使用LINQ,那么请查看for循环的效率可能与问题相同。首先,为什么有两个相互依赖的对象列表。为什么您不只有一个集合并初始化加载它的
Child
属性(例如从数据库中)?LINQ基本上用于选择,而不是仅当给定的
Foo
,您始终知道其索引
i
在数组中起作用,在原始问题中没有给出正确答案的东西。“你永远不能改变来源”-这不是真的。你一般不应该,但你绝对可以。例如,我怀疑:
parents.Select((parent,index)=>parent.Child=children[index]).Count()
实际上与循环具有相同的效果。我绝对不建议这样做,但我希望它能起作用。我建议将“可以”改为“应该”。
public static IEnumerable<TResult> Combine<TResult>(this IEnumerable<Foo> foos,
    IEnumerable<Bar> bars,
    Func<Foo, Bar, TResult> resultSelector)
{
    return foos.Zip(bars, resultSelector(foo, bar));
}
IEnumerable<Foo> foos = GetMyFoos();
IEnumerable<Bar> bars = GetBars();

var result = foos.Combine(bars, (foo, bar) => new
{
    // select the Foo and Bar properties that you plan to use in this situation
    Date = foo.Date,
    FooId = foo.Id,
    FooName = foo.Name,

    BarName = bar.Name,
    ...
})
.Where(combineResult => combineResult.Date.Year < 2000)
.GroupBy(foo => foo.Name)
.Select(...);
IEnumerable<Student> students = ...
IEnumerable<Address> addresses = ...

var studentsWithTheirAddress = students.Zip(addresses, (student, address) => new
{
    Id = student.Id,
    Name = student.Name,
    Street = address.Street,
    City = address.City,
    ...
})