linq ToArray()改变数组长度

时间:2017-04-13 11:38:33

标签: c# linq

请考虑以下事项:

Dictionary<int,int> dict = new Dictionary<int,int>();
dict.Add(1, 3);
dict.Add(3, 4);

int [] a = new int [] { 1, 2, 3 };
int [] b = new int [a.Length];

Console.WriteLine("a:");
a.Dump(); //using linqpad here

Console.WriteLine("b:");
b.Dump(); //using linqpad here

b = dict.OrderByDescending(x => x.Value).Select(x => x.Key).ToArray();
Console.WriteLine("b after linq:");
b.Dump(); //using linqpad here

结果

a: 1 2 3

b: 0 0 0

b after linq: 3 1 

我有一个现有的数组a。我创建了一个长度相同b的新数组。将具有ToArray()值的linq查询添加到新数组b后,但长度会发生变化。有没有办法保留原始数组长度,同时仍然向它添加值?

期望的结果

b after linq: 3 1 0

3 个答案:

答案 0 :(得分:2)

这是一项作业:

b = dict.OrderByDescending(x => x.Value).Select(x => x.Key).ToArray();

它替换了对变量new int [a.Length]中的数组b的引用,以及对LINQ查询创建的数组的新引用。赋值不会更改第一个数组中的值。

如果你想合并&#39;两个数组通过用第二个数组中的项替换第一个数组中的相应项,可以创建自定义扩展方法(没有默认的LINQ扩展):

public static IEnumerable<T> MergeWith<T>(
    this IEnumerable<T> source, IEnumerable<T> replacement)
{
    using (var sourceIterator = source.GetEnumerator())
    using (var replacementIterator = replacement.GetEnumerator())
    {
        while (sourceIterator.MoveNext())
            yield return replacementIterator.MoveNext()
                ? replacementIterator.Current
                : sourceIterator.Current;

        // you can remove this loop if you want to preserve source length
        while (replacementIterator.MoveNext())
            yield return replacementIterator.Current;
    }
}

用法:

b = b.MergeWith(dict.OrderByDescending(x => x.Value).Select(x => x.Key)).ToArray();

输出:

b after linq: 3 1 0

答案 1 :(得分:1)

正如谢尔盖已经发布的那样,您正在使用您的Linq声明重新分配b的内容。如果要用最多为零的零填充数组的其余部分,请在Linq语句之后使用:

Array.Resize(ref b, a.Length);

这样您就可以获得所需的结果3 1 0

请注意,此操作会创建一个新数组,并用此数组替换现有变量b

答案 2 :(得分:-1)

您只需在字典中添加“3”和“1”。 如果您想要“3 1 0”作为结果,您还需要在字典中添加“0”。