【问题标题】:Sort list of anything by relations按关系对任何内容进行排序
【发布时间】:2012-01-04 11:52:48
【问题描述】:

在我正在做的一个应用程序中,我得到了一个项目列表,以及它们之间的关系,我需要计算一个排序列表。为了好玩,让我们使用一个考试评分示例,我们知道:

  1. 约翰比简做得更好

  2. 简比卢克做得更糟

  3. 卢克比杰森做得更好

  4. Jason 做得比 Tim 还差

对于这个列表,我需要计算以下排序列表:

  1. 约翰
  2. 卢克
  3. 蒂姆
  4. 杰森

如何根据有争议的关系推导出项目在排序列表中的位置?

【问题讨论】:

  • 为什么返回'1是不正确的。路加福音 2. 约翰。 3. 简 4. 蒂姆 5. 杰森?
  • 没错。关系基本上意味着一个应该高于/低于另一个。加权位置/排序不是必需的,只是排序应该准确反映关系。

标签: algorithm list sorting numeric scoring


【解决方案1】:

如果你在这里抛出一个http://en.wikipedia.org/wiki/Topological_sorting 算法,你可以查看结果,看看是否有两个人的顺序是固定的:如果是,一个人可以从另一个人到达。如果您的数据是一致的,则拓扑排序将为您提供与您的数据一致的线性顺序,但可能暗示您的数据实际上不支持的顺序,因为缺乏比较来判断 Adam 是否真的比 Bill 做得更好。

除非您的数据非常特殊,否则您可能会发现少数情况下图中存在循环,因此根本没有顺序是一致的。您可以使用http://en.wikipedia.org/wiki/Strongly_connected_component 找到以此类循环链接的人群。

如果您必须解决嘈杂和不一致的数据,您可能不得不求助于某种统计排名系统。 http://en.wikipedia.org/wiki/Pairwise_comparison 有一种总结。进一步的网络搜索将向您展示 Bradley-Terry 模型可以通过多种方式拟合,包括逻辑回归,因此这是一个起点,当然还有大量其他评分系统,其中一些与体育和游戏如http://en.wikipedia.org/wiki/Elo_rating_system

【讨论】:

    【解决方案2】:

    从根本上说,排序需要linear order

    你需要你的关系是一个线性顺序,这意味着:

    1. a ≤ a(自反性)
    2. 如果 a ≤ b 且 b ≤ a 则 a = b(反对称)
    3. 如果 a ≤ b 且 b ≤ c 则 a ≤ c(传递性)
    4. 对于所有 a 和 b,a ≤ b 或 b ≤ a(总数)

    那么,这是什么意思?最常见的关系是线性的。例如,如果您正在谈论实际上是实数的成绩,那么是的,成绩可以线性排序。排名也是如此,因为它们再次只是实数。

    但是,例如,如果您对棋手进行排名,则不能使用他们的比赛历史。如果玩家 A 在他们的大部分比赛中击败了玩家 B,并且 B 在他们的大部分比赛中再次击败了 C,这并不意味着 A > B > C,仅仅因为 C 可能在他们的大部分比赛中击败了 A匹配。

    这也是Elo ratings 存在的原因之一,他们需要一个线性顺序来排序谁是最好的玩家,并注意 Elo 基本上只是一个实数,因此具有线性顺序。

    因此,对于考试评分,您根本没有那种线性顺序。为什么?是实数!嗯,没错,你有这个线性顺序,但你不能问这个线性顺序一切,你被限制在预定义的比较列表中,这里是:

    1. 约翰比简做得更好
    2. 简比卢克做得更糟
    3. 卢克比杰森做得更好
    4. Jason 做得比 Tim 还差

    所以,答案是:不,一般来说,如果没有任何一对元素之间的比较,就无法对列表进行排序。

    现在,我正在研究一个“最不坏”的答案,但这对我来说并不是微不足道的......


    编辑:好的,我想出了一些东西。这个想法是您将在预定义的比较列表中提取最可能的信息。然后将不在扩展比较列表中的任何比较视为相等。

    那么,你是怎么做到的呢?

    首先,对于任何 a a。然后,您将查看预定义的比较列表以查找任何比较 a a。如果你知道没有平等(没有学生的成绩相同),那就完了。否则,您必须添加所有自反性和反对称关系。你不能对整体性做任何事情。现在,您有了扩展比较列表。

    现在,采用您最喜欢的排序算法。如果您没有,quicksort 写起来很好、高效且简短。然后,每当算法要求比较 a 和 b 时,请查看您的扩展比较列表。如果比较在这里,很好,否则,将比较视为 a=b。 (注意,知道不存在等式也没关系,算法不关心)

    结果将是一个“最差”的排序列表。通常有几个可能的“最差”排序列表,但这个算法只会给你一个。


    那么,让我们举个例子。它与 OP 中给出的几乎相同,略有不同(“约翰比卢克做得更糟”而不是“简比卢克做得更糟”)。所以,我们从:

    1. 约翰比简做得更好
    2. 约翰比卢克做得更糟
    3. 卢克比杰森做得更好
    4. Jason 做得比 Tim 还差

    现在,对于每个“X 比 Y 差”,我添加“Y 比 X 好”,反之亦然。新句子以粗体显示:

    1. 约翰比简做得更好
    2. 卢克比约翰做得更好
    3. 卢克比杰森做得更好
    4. 蒂姆比杰森做得更好
    5. 简的表现比约翰差
    6. 约翰比卢克做得更糟
    7. 杰森比卢克做得更糟
    8. Jason 做得比 Tim 还差

    最后,我扫描了所有可能的句子“X has done better than Y”和“Y has done better than Z”,并加上“X has done better than Z”

    1. 约翰比简做得更好
    2. 卢克比约翰做得更好
    3. 卢克比杰森做得更好
    4. 蒂姆比杰森做得更好
    5. 卢克比简做得更好
    6. 简的表现比约翰差
    7. 约翰比卢克做得更糟
    8. 杰森比卢克做得更糟
    9. Jason 做得比 Tim 还差
    10. 简比卢克做得更糟

    扩展表已完成。

    现在让我们看一下快速排序的伪代码:

      function quicksort('array')
          if length('array') ≤ 1
              return 'array'  // an array of zero or one elements is already sorted
          select and remove a pivot value 'pivot' from 'array'
          create empty lists 'less' and 'greater'
          for each 'x' in 'array'
              if 'x' ≤ 'pivot' then append 'x' to 'less'
              else append 'x' to 'greater'
          return concatenate(quicksort('less'), 'pivot', quicksort('greater'))
    

    与标准快速排序的唯一区别在于您通常无法知道问题if('x' ≤ 'pivot') ... 的答案。因此,相反,如果x=Lukepivot = Tim,您在表中查找“Luke has done than Tim”这句话。如果你找到它,那么你认为答案是true 并做append 'x' to 'less'。如果您在表中找到“Luke 比 Tim 做得更好”,那么您认为答案是错误的,您会选择 append 'x' to 'greater'。最后,如果你找不到上面提到的两个句子中的任何一个,你就像'x' == 'pivot',你做append 'x' to 'less'

    【讨论】:

    • 您的解决方案听起来很酷,但我无法从代码方面真正弄清楚...您能更具体一点吗?我会接受你的回答......只需要更多地理解它。 (例如,无法理解 aa 部分,无法理解我需要将其绑定在一起的代码)
    • 我给你详细解释了我的东西=)
    猜你喜欢
    • 2021-09-18
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 2017-05-02
    • 2011-12-06
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    相关资源
    最近更新 更多