【问题标题】:How to sort a generic sequence with pinned elements如何使用固定元素对通用序列进行排序
【发布时间】:2019-10-14 02:59:10
【问题描述】:

我有一个数字序列,我需要对它们进行排序,除了一些应该保持在初始位置的数字。例如 假设我的顺序是:

33, 20, 48, 17, 48, 36, 20, 12, 25

...数字 20 和 25 应保持固定。然后对序列进行排序后,我应该得到以下结果:

12, 20, 17, 33, 36, 48, 20, 48, 25

如何实现这种受限排序?我要实现的方法有这个签名:

public static IEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, bool> pinPredicate)
{
    //...
}

然后可以使用此方法产生理想的结果,如下所示:

var source = new int[] { 33, 20, 48, 17, 48, 36, 20, 12, 25 };
var result = source.OrderBy(n => n, n => n == 20 || n == 25);

我直接尝试通过链接 LINQ 方法 SelectOrderBy 来解决这个问题,但失败了。这个问题似乎太复杂了,无法使用单链 LINQ 方法解决。

【问题讨论】:

  • 他们被钉住是因为他们的价值还是因为他们的索引
  • 最简单的解决方案可能是有效地“删除”您不想排序的值,然后在排序完成后将它们重新插入。
  • 请求第三方库是题外话。询问“关于我如何自己实现它的想法”太宽泛了。人们应该做足够的研究并做出足够重要的尝试,以首先实际解决他们自己的问题,以使他们的问题保持在主题上并且足够具体以适合 Stack Overflow。
  • 坦率地说,发布的答案清楚地证明了这一点。提供了两种不同的算法,但尚未被您接受为答案。相反,一个新的对话已经开始,因为该问题的作者试图弄清楚你真正想要的是什么?同样,这是太宽泛的定义。您正在通过自己的行动确切地证明为什么您的问题过于宽泛
  • 我认为我很清楚:这个问题需要自己付出一些努力来实现。随意使用 cmets 中已经提供的建议。提供minimal reproducible example,说明该代码的作用、该尝试以何种方式不符合您的目标,以及具体您需要哪些改进方面的帮助。

标签: c# algorithm linq sorting


【解决方案1】:

您可以试试这个 LINQ 解决方案。

private static IEnumerable<int> PinnedSort(IEnumerable<int> numbers, ISet<int> pinnedNumbers)
{
    // Extract pinned numbers into (number, index) tuples
    // Might be cleaner to make a class here instead
    var onlyPinnedNumbers = numbers
        .Select((number, index) => (number, index))
        .Where(pair => pinnedNumbers.Contains(pair.number));

    // Sort other numbers that don't exist in pinned numbers set
    var sortedNumbers = numbers
        .Where(number => !pinnedNumbers.Contains(number))
        .OrderBy(number => number)
        .ToList();

    // Insert pinned numbers into sorted list
    foreach (var (number, index) in onlyPinnedNumbers)
    {
        sortedNumbers.Insert(index, number);
    }

    return sortedNumbers;
}

可以这样运行:

var numbers = new int[] { 33, 20, 48, 17, 48, 36, 20, 12, 25 };

// Store pinned numbers in hashset, for O(1) lookups
var pinnedNumbers = new HashSet<int> { 20, 25 };

var pinnedSort = PinnedSort(numbers, pinnedNumbers);

Console.WriteLine("{ " + string.Join(", ", pinnedSort) + " }");

输出:

{ 12, 20, 17, 33, 36, 48, 20, 48, 25 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多