C# 如何使用LINQ(整体)分配集合中的属性

C# 如何使用LINQ(整体)分配集合中的属性,c#,arrays,linq,C#,Arrays,Linq,我有一个Foo类型的数组或集合,其属性值为double类型。如果我有一个值列表,如何使用LINQ将它们分配给我的集合 基本上我想要的是相反的 var values = list.Select((item)=>item.Value).ToArray(); 示例代码: class Foo { public double Value { get; set; } // many other properties } static void Main() { // ex

我有一个Foo类型的数组或集合,其属性值为double类型。如果我有一个值列表,如何使用LINQ将它们分配给我的集合

基本上我想要的是相反的

var values = list.Select((item)=>item.Value).ToArray();
示例代码:

class Foo
{
    public double Value { get; set; }
    // many other properties
}

static void Main() 
{
    // example initializations
    var list = new Foo[4];

    // somewhere else in the code
    var values = GetValues();
    // returns { 10.0, 12.0, 15.5, 17.3 }

    // Q? Can I do this in LINQ with one statement,
    // without re-creating list. I just want to set
    // one property of Foo based on my array.

    // assign values (I know lengths will match)
    for(int i=0; i<list.Length; i++)
    {
        list[i].Value = values[i];
    }

}
但这是可行的,尽管这感觉像是一个乱七八糟的问题

list.Zip(values, (leg, val) => leg.Value=val ).ToArray();
注:这与类似,只是我想分配列表中的所有值,而不仅仅是筛选一个值并获取对它的引用

PS2。如果Foo是一种值类型,这会更难吗

仅供参考。在Fortran中,即使列表是一个数组,也要执行列表%value=值。在Fortran语言中,结构数组同样也是数组结构。朱莉娅,我希望有其他语言的Python?我也这么做了。但是,C类型语言不支持:-

这:

var list = values.Select(item =>new Foo{Value=item}).ToArray();
同:

for(int i=0; i<list.Length; i++)
{
  list[i].Value = values[i];
}

您可以在列表上使用ForEach

class Program
{
    static void Main(string[] args)
    {
        int[] x = { 1, 2, 3 };
        Foo[] y = new Foo[]{ new Foo{Name="a"},new Foo{Name="b"},new Foo{Name="c"}};

        int i = 0;
        y.ToList().ForEach(a => a.Value = x[i++]);

        foreach (Foo f in y) 
          Console.Out.WriteLine(f.ToString());

        //or even ;)
        y.ToList().ForEach(a => Console.Out.WriteLine(a.ToString));
    }
}
class Foo
{
    public int Value { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name + Value;
    }
}
我现在想不出一个办法来摆脱int I=0线

但如果你这样做了,请考虑下面的论点:

编辑:好的,所以有人对不是LINQ的收费表提出了异议。这样做:

class Program
{
    static void Main(string[] args)
    {
        int[] x = { 1, 2, 3 };
        Foo[] y = new Foo[]{ new Foo{Name="a"},new Foo{Name="b"},new Foo{Name="c"}};

        int i = 0;
        y.Select(a => a.Value = x[i++]).ToArray();

        foreach (Foo f in y) 
          Console.Out.WriteLine(f.ToString());
    }
}
class Foo
{
    public int Value { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name + Value;
    }
}
Select是LINQ,ToArray使操作在循环打印值时实际发生。。但这并不是查询系统的预期目的

它的高低是:

问:我如何

A:你不知道

你用的是fortran


答:您编写一个foreach循环,就像其他对生成可读、自解释、可维护的代码感兴趣的人一样

您可以创建一个类似LINQ的扩展方法,它不会返回IEnumerable,而是修改传入的结构的IEnumerable或IList

public static class ExtentionMethods
{
    public static void Update<TItem, TValue>(this IEnumerable<TItem> @this, IEnumerable<TValue> items, Action<TItem, TValue> applyAction) 
        where TItem : class
    {
        using (var thisEnumerator = @this.GetEnumerator())
        using (var itemEnumerator = items.GetEnumerator())
        {
            while (thisEnumerator.MoveNext() && itemEnumerator.MoveNext())
            {
                applyAction(thisEnumerator.Current, itemEnumerator.Current);
            }
        }
    }

    public delegate void UpdateAction<TItem, TValue>(ref TItem item, TValue newValue);

    public static void Update<TItem, TValue>(this IList<TItem> @this, IEnumerable<TValue> items, UpdateAction<TItem, TValue> applyAction)
where TItem : struct 
    {

        using (var itemEnumerator = items.GetEnumerator())
        {
            for (int i = 0; i < @this.Count && itemEnumerator.MoveNext(); i++)
            {
                var temp = @this[i];
                applyAction(ref temp, itemEnumerator.Current);
                @this[i] = temp;
            }
        }
    }
}

namespace SandboxConsole
{
    class Program
    {
        class Foo
        {
            public double Value { get; set; }
        }
        struct Foo2
        {
            public double Value { get; set; }
        }

        private static IReadOnlyList<double> GetValues()
        {
            return new[] { 10.0, 12.0, 15.5, 17.3 };
        }

        static void Main()
        {
            // example initializations
            var list = new Foo[4];
            var list2 = new Foo2[4];

            // somewhere else in the code
            var values = GetValues();
            // returns { 10.0, 12.0, 15.5, 17.3 }

            list.Update(values, (item, value) => item.Value = value);
            list2.Update(values, (ref Foo2 item, double value) => item.Value = value);
        }
    }
}

使用Zip将要更新的项与要注入的值配对是很好的,但这就是您应该做的。一旦您将它们配对,您应该在这些对上循环进行更新

var pairs = list.Zip(values, (leg, val) => new { leg, val });
foreach (var pair in pairs)
    pair.leg.Value = pair.val;

Linq旨在帮助您查询数据,而不是修改数据。

Linq通常是功能性的,它表示查询。您通常不会期望LINQ查询有副作用。就我个人而言,我会坚持某种循环。你们的科学家全神贯注于他们是否能做到,他们没有停下来思考他们是否应该。。。伊恩·马尔科姆博士——我想澄清我编辑的问题。我不想再创造富了。所以没有新的Foo语句。我想为Foo分配值或单个属性,那么最好使用for或foreach循环。要实现foreach,您可以使用var list=values.Selectv,i=>new{Value=v,Index=i}不使用LINQT的方法。对于被否决的人,请告诉我您认为对我的答案没有帮助的地方。op没有寻找实际的LINQ解决方案,因为他不关心list.Zipvalues,leg,val=>leg.Value=val.ToArray的结果;在他的示例中,他只需要一个单行扩展方法,该方法可以执行不会像list.Zipvalues,leg,val=>leg.Value=val.ToArray那样冗长的操作;我想可能是OP把他们都否决了。。不过,提出一个在概念上没有合理答案的问题,然后对所有提出令人费解的胡言乱语的人投反对票,这有点像朗姆酒交易answer@CaiusJard因此,这个故事的寓意是,不要试图发布没有合理答案的问题的答案,不?Servy我认为我的答案是合理的。它真正做的就是把现有的foreach压缩成一个扩展方法。@ScottChamberlain我看不出它比简单地使用循环有什么好处。与这里的其他答案相比,它没有那么糟糕,但它仍然没有真正增加任何价值,而且它仍然有一些成本。到目前为止,Linq的最佳使用。这一点很清楚,因为它比不返回值的Zip语句更能显示意图。此外,延迟执行似乎只执行一个循环。
var pairs = list.Zip(values, (leg, val) => new { leg, val });
foreach (var pair in pairs)
    pair.leg.Value = pair.val;