在LINQ中解压缩列表

本文关键字:列表 解压缩 LINQ | 更新日期: 2023-09-27 18:26:23

在规格不好的接口中,我们有

int[] userIdList; // ids of all users to display
string[] userNameList; // names of all users to display

限制条件是userIdList[i]始终包含名为userNameList[i]的用户的ID。

新的要求是按名称对用户进行排序:我将接受这两个列表,按名称排序,并返回两个仍然存在上述限制的列表。

当然,我可以自己实现排序函数,但我认为单行linq语句可以做得更好?我上了

userNameList.Zip(userIdList, (name, id) => new {name, id}).OrderBy(a=>a.name).

但现在我不知道如何再次解压缩列表。。。

在LINQ中解压缩列表

int[] userIdList = zipped.Select(x => x.id).ToArray();
string[] userNameList = zipped.Select(x => x.name).ToArray();

对于输入:

 int[] userIdList = new []{ 1,5,3,6 }; // ids of all users to display
 string[] userNameList = new []{ "Farix", "Doubles", "Rogue", "Splinter" }; // names of all users to display

你可以做:

 Array.Sort(userNameList, userIdList);

然后,您将获得与LINQ代码完全相同的结果,但使用一个更简单的表达式,该表达式不会像LINQ代码中那样分配新的数组,而只是重新排序现有数组中的项,这样效率高得多。

如果集合是列表类型,则可以解压缩。您可以编写自己的解压缩扩展方法来实现这一点:

 public static class ListExtensions
    {
        public static void Unzip<T, T1, T2>(this IList<T> source, Func<T, T1> firstSelector, Func<T, T2> secondSelector,
            out IEnumerable<T1> first, out IEnumerable<T2> second)
        {
            first = source.Select(firstSelector);
            second = source.Select(secondSelector);
        }
    }

用法:

enumerableEntitiesToUnzip.ToList().Unzip(e=>e.Prop1,e=>e.Prop2, out var first, out var second)

我想要类似Scala unzip()的东西,所以我使用了@zafar 的解决方案

public static class ListExtensions
{
    public static (IEnumerable<T1>, IEnumerable<T2>) Unzip<T1, T2>(
        this IEnumerable<(T1, T2)> source
    ) => source.Unzip(tp => tp.Item1, tp => tp.Item2);
    public static (IEnumerable<T1>, IEnumerable<T2>) Unzip<T1, T2>(
        this IEnumerable<(T1, T2)> source,
        Func<(T1, T2), T1> f1,
        Func<(T1, T2), T2> f2
    ) => (source.Select(f1), source.Select(f2));
}