【问题标题】:Using the TList class to reorder multiple fields使用 TList 类对多个字段进行重新排序
【发布时间】:2021-08-25 07:44:44
【问题描述】:
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 和它报告的代码做了一些测试,但我得到了完全不同的结果。

谁能给我指路?

【问题讨论】:

  • (item1-&gt;string1 &lt; item2-&gt;string1)true 时,(item1-&gt;string1 &gt; item2-&gt;string1) 必须为false。你为什么还要检查?您的 return 声明看起来有误。
  • 我不检查返回值。不幸的是,我找不到详细解释 Sort () 方法使用的文档。
  • @David 然后你didn't look very hard
  • 我建议不要这样做 StrToInt64(item1-&gt;number1) - StrToInt64(item2-&gt;number1) - 如果数字非常大,您可能会遇到算术溢出(您的大正数突然变为负数,因此排序行为不端)。不过,在大多数情况下,使用 int64 可能会侥幸成功。

标签: c++ c++builder


【解决方案1】:

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

Item1Item2 是列表中的 2 个元素。当这些被传递给TListSortCompare 函数时,Sort 方法询问它们应该处于哪个顺序。比较返回一个由Item1Item2 的相对值确定的值,如下表所示:

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

您的函数不满足该要求。

item1-&gt;string1 小于item2-&gt;string1 时,当您应该返回负值时,您将返回 0。

否则,您将返回从item1-&gt;number1 中减去item2-&gt;number1 的结果。但是当item1-&gt;string1 大于或等于item2-&gt;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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-06
    • 2011-09-14
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多