在C#中,如何在列表中间"最大"值的列表中订购项目

Ced*_*icB 12 c# linq list

我有一段时间难过这个.我想获取一个列表并订购列表,以便最大价格的产品最终位于列表中间.而且我也想做相反的事情,即确保价格最高的项目最终在列表的外边界上.

想象一下像这样的数据结构.. 1,2,3,4,5,6,7,8,9,10

在第一个场景中,我需要回到1,3,5,7,9,10,8,6,4,2在第二个场景中,我需要回到10,8,6,4,2,1,3 ,5,7,9

该列表可能有超过250个项目,数字将不会均匀分布,并且它们不会是连续的,我想尽量减少复制.数字将包含在Product对象中,而不是简单的原始整数.

是否有一个我没有看到的简单解决方案?

有什么想法吗.

所以对于那些想知道我在做什么的人,我根据计算出的字体大小来订购商品.这是我去的代码......

实施......

private void Reorder()
{
    var tempList = new LinkedList<DisplayTag>();
    bool even = true;
    foreach (var tag in this) {
        if (even)
            tempList.AddLast(tag);
        else
            tempList.AddFirst(tag);

        even = !even;
    }

    this.Clear();
    this.AddRange(tempList);
}
Run Code Online (Sandbox Code Playgroud)

考试...

[TestCase(DisplayTagOrder.SmallestToLargest, Result=new[]{10,14,18,22,26,30})]
[TestCase(DisplayTagOrder.LargestToSmallest, Result=new[]{30,26,22,18,14,10})]
[TestCase(DisplayTagOrder.LargestInTheMiddle, Result = new[] { 10, 18, 26, 30, 22, 14 })]
[TestCase(DisplayTagOrder.LargestOnTheEnds, Result = new[] { 30, 22, 14, 10, 18, 26 })]
public int[] CalculateFontSize_Orders_Tags_Appropriately(DisplayTagOrder sortOrder)
{
    list.CloudOrder = sortOrder;
    list.CalculateFontSize();

    var result = (from displayTag in list select displayTag.FontSize).ToArray();
    return result;
}
Run Code Online (Sandbox Code Playgroud)

用法......

public void CalculateFontSize()
{
    GetMaximumRange();
    GetMinimunRange();
    CalculateDelta();

    this.ForEach((displayTag) => CalculateFontSize(displayTag));

    OrderByFontSize();
}

private void OrderByFontSize()
{
    switch (CloudOrder) {
        case DisplayTagOrder.SmallestToLargest:
            this.Sort((arg1, arg2) => arg1.FontSize.CompareTo(arg2.FontSize));
            break;
        case DisplayTagOrder.LargestToSmallest:
            this.Sort(new LargestFirstComparer());
            break;
        case DisplayTagOrder.LargestInTheMiddle:
            this.Sort(new LargestFirstComparer());
            Reorder();
            break;
        case DisplayTagOrder.LargestOnTheEnds:
            this.Sort();
            Reorder();
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ian*_*cer 9

适当的数据结构是LinkedList因为它允许您有效地添加到任何一端:

        LinkedList<int> result = new LinkedList<int>();

        int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        Array.Sort(array);

        bool odd = true;

        foreach (var x in array)
        {
            if (odd)
                result.AddLast(x);
            else
                result.AddFirst(x);
            odd = !odd;
        }

        foreach (int item in result)
            Console.Write("{0} ", item);
Run Code Online (Sandbox Code Playgroud)

没有额外的复制步骤,没有反向步骤,......每个节点只需要很小的开销用于存储.


Joh*_*n K 6

C#Iterator版本

(非常简单的代码,以满足所有条件.)

一个功能来统治它们!不使用中间存储集合(请参阅yield关键字).根据参数将大数字排序到中间或侧面.它是作为C#迭代器实现的

// Pass forward sorted array for large middle numbers,
//  or reverse sorted array for large side numbers.
//
public static IEnumerable<long> CurveOrder(long[] nums) {

    if (nums == null || nums.Length == 0)
        yield break; // Nothing to do. 

    // Move forward every two.
    for (int i = 0;  i < nums.Length;  i+=2)
        yield return nums[i];

    // Move backward every other two. Note: Length%2 makes sure we're on the correct offset.
    for (int i = nums.Length-1 - nums.Length%2;  i >= 0;  i-=2)
        yield return nums[i];
}
Run Code Online (Sandbox Code Playgroud)

示例用法

例如,使用数组 long[] nums = { 1,2,3,4,5,6,7,8,9,10,11 };

从正向排序顺序开始,将高数字压入中间.

Array.Sort(nums); //forward sort
// Array argument will be:  { 1,2,3,4,5,6,7,8,9,10,11 };
long[] arrLargeMiddle = CurveOrder(nums).ToArray();
Run Code Online (Sandbox Code Playgroud)

产量:1 3 5 7 9 11 10 8 6 4 2

或者,从反向排序顺序开始,将高数字推向两侧.

Array.Reverse(nums); //reverse sort
// Array argument will be:  { 11,10,9,8,7,6,5,4,3,2,1 };
long[] arrLargeSides = CurveOrder(nums).ToArray();
Run Code Online (Sandbox Code Playgroud)

产生:11 9 7 5 3 1 2 4 6 8 10

重要的命名空间是:

using System;
using System.Collections.Generic;
using System.Linq;
Run Code Online (Sandbox Code Playgroud)

注意:迭代器会决定是否使用中间存储来决定调用者.调用者可能只是foreach在结果上发出循环.


扩展方法选项

(可选)更改静态方法标头以使用this修饰符 public static IEnumerable<long> CurveOrder(this long[] nums) { 并将其放在命名空间中的静态类中;
然后直接在任何long []数组实例上调用order方法,如下所示:

Array.Reverse(nums); //reverse sort
// Array argument will be:  { 11,10,9,8,7,6,5,4,3,2,1 };
long[] arrLargeSides = nums.CurveOrder().ToArray();
Run Code Online (Sandbox Code Playgroud)

只是一些(不需要的)语法糖来混合一些东西以获得乐趣.这可以应用于采用数组参数的问题的任何答案.