3

谁能帮我对以下字符串列表进行排序:

List< String > 包含坐标

[0] “0 0”
[1] “0 1”
[2] “0 2”
[3] “0 3”
[4] “1 1”
[5] “1 2”
[6] “1 3”

虽然它可能并不总是按照那个顺序,但我想通过排序/排序来确保它是这样的(按 X 坐标 ASC 排序,然后按 Y 坐标 ASC 排序)

我已经尝试过了,但它根本不会改变列表?- 见下文

boardObjectList.OrderBy(p => (p.Split())[0]).ThenBy(p=> (p.Split())[1]);

有任何想法吗?

谢谢,
JP

4

3 回答 3

5

OrderBy并且ThenBy不要修改原始列表,它们只会返回一个新列表(以 an 的形式IEnumerable<>)。您需要做的是List<>从结果中创建一个新的IEnumerable<>,如下所示:

// Note that we are assigning the variable to a new list
boardObjectList = boardObjectList.OrderBy(p => (p.Split())[0])
                                 .ThenBy(p => (p.Split())[1])
                                 .ToList(); // Also note that we call ToList,
                                            // to get a List from an IEnumerable

将数字存储在字符串中并尝试排序时,您会得到奇怪的结果。我建议将您的代码更改为:

boardObjectList = boardObjectList.OrderBy(p => int.Parse(p.Split()[0]))
                                 .ThenBy(p => int.Parse(p.Split()[1]))
                                 .ToList();

此方法在排序之前将字符串转换为整数。这样做的原因是字符串排序按字母顺序排序,导致排序如下:

1
10
11
12
2
3
4
5
6
7
8
9
于 2012-08-11T13:22:37.033 回答
1

这是一个可能的解决方案。我对整数坐标使用单独的结构,并将拆分字符串转换为它的实例。

// Defined elsewhere
struct Coord
{
    public int x;
    public int y;
}


// Where you're doing your work...
var intCoords = new List<Coord>();
foreach (var coord in boardObjectList)
{
    var str = coord.Split(new char[] { ' ' });
    intCoords.Add(new Coord() { 
        x = Int32.Parse(str[0]), 
        y = Int32.Parse(str[1])
    });
}

// Do the actual sort. Ensure you assign the result to a variable
var newCoords = intCoords.OrderBy(x => x.x).ThenBy(x => x.y).ToList();
于 2012-08-11T14:05:16.433 回答
0

当然,它根本不会改变列表——LINQ 不会修改底层集合,它只是创建查询。

您所追求的是将查询结果存储在一个新列表中:

boardObjectList = boardObjectList.OrderBy(p => (p.Split())[0]).ThenBy(p=> (p.Split())[1]).ToList();

编辑:再看一眼。你不应该像那样比较字符串——如果这些“数字”中的任何一个大于“9”会发生什么?这是更新的解决方案:

boardObjectList = boardObjectList.Select(p => new { P = p, Split = p.Split() } ).
    OrderBy(x => int.Parse(x.Split[0])).ThenBy(x => int.Parse(x.Split[1])).
    Select(x => x.P).ToList();

EDIT2:您也可以在没有 LINQ 的情况下使用更少的内存开销来做到这一点:

boardObjectList.Sort((a, b) =>
    {
        // split a and b
        var aSplit = a.Split();
        var bSplit = b.Split();
        // see if there's a difference in first coordinate
        int diff = int.Parse(aSplit[0]) - int.Parse(bSplit[0]);
        if (diff == 0)
        {
            // if there isn't, return difference in the second
            return int.Parse(aSplit[1]) - int.Parse(bSplit[1]);
        }
        // positive if a.x>b.x, negative if a.x<b.x - exactly what sort expects
        return diff;
    });
于 2012-08-11T13:18:05.723 回答