使用 TList class 重新排序多个字段

Using the TList class to reorder multiple fields

int __fastcall ListSortFunc1(void *Item1, void *Item2)
{
    MyStruct *item1 = (MyStruct*)Item1;
    MyStruct *item2 = (MyStruct*)Item2;

    return (item1->string1 < item2->string1) ? (item1->string1 > item2->string1) :
            StrToInt64(item1->number1) - StrToInt64(item2->number1);
}

看了网上的文档,对Sort方法的使用不是很清楚

我的需要是重新排序两个或更多字段。目前,我必须重新排序一个文件,其中第一个字段是数字,第二个是日期,第三个是字符串,第四个仍然是字符串。

我用 Excel 和它报告的代码做了一些测试,但我得到了完全不同的结果。

谁能给我指路?

TList::Sort() 传递了一个回调函数,该函数在排序期间调用以比较列表中的值对。回调应该符合 TListSortCompare 类型的规范。根据其文档:

Item1 and Item2 are 2 elements from the list. When these are passed to the TListSortCompare function, the Sort method is asking which order they should be in. The comparison returns a value determined by the relative values of Item1 and Item2, as shown in this table:

Value Description
>0 (positive) Item1 is greater than Item2
0 Item1 is equal to Item2
<0 (negative) Item1 is less than Item2

您的功能不满足该要求。

item1->string1 小于 item2->string1 时,你 return 0 而你应该 return 负值。

否则,你return就是item1->number1减去item2->number1的结果。但是当 item1->string1 大于或等于 item2->string1 时,您正在比较 number1 字段。只有当 string1 字段相等时,您才应该比较 number1 字段。此外,如果 number1 字段具有较大的值,则使用减法会有溢出的风险。

尝试更像这样的东西:

int __fastcall ListSortFunc1(void *Item1, void *Item2)
{
    MyStruct *item1 = static_cast<MyStruct*>(Item1);
    MyStruct *item2 = static_cast<MyStruct*>(Item2);

    if (item1->string1 == item2->string1)
    {
        // simply subtracting the values could lead to integer overflows
        // for large values, so just compare the values as-is...

        // Also: why are these not stored as __int64 to begin with?
        __int64 int1 = StrToInt64(item1->number1);
        __int64 int2 = StrToInt64(item2->number1);

        if (int1 < int2) return -1;
        if (int1 > int2) return 1;
        return 0;
    }
    else
    {
        return (item1->string1 < item2->string1) ? -1 : 1;
        // or:
        return CompareStr(item1->string1, item2->string1); // case sensitive
        // or:
        return CompareText(item1->string1, item2->string1); // case insensitive
    }
}