【问题标题】:Sort an array of objects according to another array of objects in C# [duplicate]根据C#中的另一个对象数组对对象数组进行排序[重复]
【发布时间】:2021-01-13 20:36:11
【问题描述】:

我有两个对象。我想根据第二个对象的QuickLinks 对第一个对象的QuickLinks 属性进行排序。应该是基于QuickLinkContent.ConfigId

NavigationMenuContent nmc1 = new NavigationMenuContent();
NavigationMenuContent nmc2 = new NavigationMenuContent();

public class NavigationMenuContent
    {
        public int LanguageID { get; set; }

        public QuickLinkContent[] QuickLinks { get; set; }
    }

public class QuickLinkContent
    {
        public Guid ConfigID { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public string Url { get; set; }

        public Guid? ServiceProviderID { get; set; }

        public SchemeContentFile Document { get; set; }
    }

我试过这样做:

nmc1.QuickLinks = nmc1.QuickLinks.OrderBy(q => nmc2.QuickLinks.ToList().IndexOf(q.ConfigID));

但出现错误:

Cannot convert from System.Guid to QuickLnkContent.

【问题讨论】:

  • 您说要对nmc1 列表进行排序,但您正在尝试对QuickLinks 数组进行排序。那么你实际上想要排序的是什么?
  • 我要根据 nmc2.QuickLinks 对 nmc1.QuickLinks 进行排序
  • 这是什么意思?例如,如果我说“我想根据名字的字母降序对这个 Person[] 进行排序”——这是有道理的。但是“我想根据那个 Person[] 对这个 Person[] 进行排序”——这不是一个规范任何东西
  • nmc1 是一个列表。它没有属性QuickLinks
  • @SergeyBerezovskiy 抱歉,我已经更新了问题

标签: c# linq sorting


【解决方案1】:

我会使用字典来做到这一点。

Dictionary<Guid, int> map =
    nmc2
        .QuickLinks
        .Select((x, n) => (x, n))
        .ToDictionary(z => z.x.ConfigID, z => z.n);

nmc1.QuickLinks =
    nmc1
        .QuickLinks
        .OrderBy(x => map[x.ConfigID])
        .ToArray();

【讨论】:

  • 这通常是更快的方法
【解决方案2】:

创建有序配置 ID 数组:

var orderedIds = nmc2.QuickLinks.Select(ql => ql.ConfigID).ToArray();

然后用它来订购链接

nmc1.QuickLinks = nmc1.QuickLinks
   .OrderBy(ql => Array.IndexOf(orderedIds, ql.ConfigID))
   .ToArray();

【讨论】:

  • O(n2) 操作。其他解决方案通常会更快
  • @Charlieface 首先是过早的优化。您不想创建字典来对包含 5 个项目的数组进行排序。其他解决方案将失败 1) 当 nmc1 具有唯一项目时,2) 当 nmc2 具有重复项时。所以你(也许)节省了几滴 cpu,但有更多的代码需要维护,还有两个问题需要处理
【解决方案3】:

使用数组扩展的方法,一般可以解决这个问题:

public static int IndexOfBy<T, TKey>(this T[] a, TKey target, Func<T,TKey> keyFn, EqualityComparer<TKey> cmp = null) {
    cmp = cmp ?? EqualityComparer<TKey>.Default;
    for (int j1 = 0; j1 < a.Length; ++j1) {
        if (cmp.Equals(keyFn(a[j1]), target))
            return j1;
    }
    return -1;
}

扩展方法可用,你可以使用OrderBy:

nmc1.QuickLinks = nmc2.QuickLinks.OrderBy(q => nmc2.QuickLinks.IndexOfBy(q.ConfigID, q2 => q2.ConfigID)).ToArray();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2016-06-02
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    相关资源
    最近更新 更多