我有一个(类)类型Foo
的数组或集合,其属性Value
的类型为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 );
但这有效,虽然它感觉像是一个kludge
list.Zip(values, (leg, val) => leg.Value=val ).ToArray();
PS。这类似于assign value using linq,除了我想要分配列表中的所有值,而不只是过滤一个并获得对它的引用。
PS2。如果Foo
是值类型,那会更难。
FYI。在Fortran
中,即使list%value = values
是一个数组,也会list
。在Fortran中,结构数组也等同于数组结构。我希望其他语言(Python,Julia?)也做同样的事情。 C
类型的语言不是: - (
答案 0 :(得分:3)
很好,您使用Zip
将要更新的项目与要注入的值配对,但这就是您应该做的所有事情接着就,随即。一旦你配对它们,你应该遍历对来进行更新。
var pairs = list.Zip(values, (leg, val) => new { leg, val });
foreach (var pair in pairs)
pair.leg.Value = pair.val;
Linq旨在帮助您查询数据,而不是对其进行修改。
答案 1 :(得分:0)
您可以创建类似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);
}
}
}
答案 2 :(得分:-2)
此:
var list = values.Select(item =>new Foo{Value=item}).ToArray();
同样:
for(int i=0; i<list.Length; i++)
{
list[i].Value = values[i];
}
答案 3 :(得分:-3)
您可以在列表中使用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
行的方法
但如果你这样做,请考虑https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/中提出的论点?
编辑:好的,所以有人认为它不是LINQ(ToList()是)。这样做:
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在循环打印值时实际发生了动作..虽然这不是查询系统的预期目的
高而缺乏:
问:“我怎么......”答:你没有
答:你使用fortran
答:你编写一个foreach循环,就像其他任何有兴趣生成可读,自解释,可维护代码的人一样