计算一次比较两个事物的比较等级

Calculate comparative rank of things compared two at a time

当输入数据如下时,如何计算表达一个人相对偏好的10个事物的权重:

包含 10 个事物的列表以随机对的形式出现(忽略顺序,因此可能会显示 A 对 B,或 B 对 A,但不会同时显示;而不是一个项目本身);

A is better than B
D is better than F
H is better than B
C is better than J

等等

有没有办法对这样的数据中的 10 个项目进行排名或加权?有没有办法将序列从 10! / (2! (10 - 2)!) =45 个问题。

你在这里做了一个危险的心理假设:你假设 "better than" 关系是传递的,所以 from

A > B
B > C

紧随其后

A > C

也就是说,不失一般性,不是人类偏好的情况。因此,这使您的整个方法受到质疑。

但是,如果您可以证明该假设是正确的,那么,这可以分解为排序问题。那里有一大堆排序算法,它们仅依赖于排序关系“>”的存在。那么你的体重就是排序列表中的位置。

现实世界中的每一种编程语言都可能有一个包含至少一种排序算法的库;大多数语言还有一种方法可以指定调用哪个函数来比较两个元素,所以这实际上归结为使用未排序的列表调用排序函数和比较两个事物时调用的函数。

如果不能做出 "better than" 关系传递的假设,事情就会变得复杂得多。基本上,您可以构建一个有向图并尝试找到通过它的路径,但该图可能不是无循环的,并且可能没有明确的可能性来分配任何权重。

关于如何测试这些东西,已有数十年的心理学方法研究;我建议找一所提供心理学课程的大学并询问那里的人。

为了使用这样的规则对数据进行排名,关系 "better" 必须是 transitive

so A vs B might be shown, or B vs A, but not both

这是朝着正确方向迈出的一步,但这不是完全可传递的。您仍然可以这样做:

A is better than B
B is better than C
C is better than A

现在你有一个循环,所以上面的三个规则不能用来对项目进行排名。

没有周期的情况下可以按照规则下单。然而,排序不一定是唯一的。例如,如果您的规则如下所示

A is better than B
C is better than B

并且您需要订购{A, B, C} "ACB" 和 "CAB" 都符合您的规则。

如果你正在寻找任何基于规则的一致排序,你可以先构建一个由你的"X is better than Y"规则导出的树,然后使用这棵树来决定你的十个项目的相对顺序。

TL;DR: 将列表中的每个元素与其他元素进行比较,并为获胜的选择分配权重或值。然后根据每个元素获得的“胜利”次数对每个元素进行排名。

这些确实是很好的有效回应,提出了需要提出的限制,但它们没有提供解决方案。我提供一个...

在进行相对比较时,在此示例中,根据主观偏好进行排名,无疑会缺乏一致性,从而破坏传递完整性。但是,你可以克服这个。如何?好吧,使用问题中的建议:权重。

将列表中的每个元素与其他元素进行比较,并为胜出的选择分配权重或值。然后根据每个元素获得的“胜利”次数对每个元素进行排名。

而且每次获胜的权重不必相同。例如,如果一个元素击败了一个排名非常高或排名最高的元素,它会获得额外的分数或其他东西。 Idk,疯了!

所以,这不是一个科学明确的排名系统(如果没有 objective 测量,你永远不会得到它)但我认为通过这种方法,你可以非常接近。

我写了一个简单的 java 命令行程序来比较水果。 下面是我的解决方案,它对我正在寻找的东西“足够好”。我希望其他人能够发现这有帮助。

package com.example;

import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;

public class ComparativeRanking {

    public static void main(String[] args) throws Exception {
        ComparativeRanking instance = new ComparativeRanking();
        final List<Fruit> fruits = Lists.newArrayList(
                new Fruit("banana"),
                new Fruit("apple"),
                new Fruit("kiwi"),
                new Fruit("strawberry"),
                new Fruit("mango"));
        Fruit[] fruitArray = fruits.toArray(new Fruit[0]);
        instance.compute(fruitArray);
    }

    void compute(Fruit[] fruitArray) throws Exception {
        for (int i = 0; i < fruitArray.length; i++) {
            for (int k = i + 1; k < fruitArray.length; k++) {
                Fruit choice1 = fruitArray[i];
                Fruit choice2 = fruitArray[k];
                System.out.println(String.format("Enter '1' for %s and '2' for %s", choice1.name, choice2.name));
                Scanner scanner = new Scanner(System.in);
                int selection = scanner.nextInt();
                switch (selection) {
                    case 1:
                        choice1.addWin();
                        break;
                    case 2:
                        choice2.addWin();
                        break;
                    default:
                        throw new Exception("Hey idiot, pick 1 or 2.");
                }
            }
        }

        List<Fruit> fruitsRankedByWins = Lists.newArrayList(fruitArray)
                .stream()
                .sorted(Comparator.comparing(Fruit::getWins).reversed())
                .collect(Collectors.toList());

        System.out.println("Result:");
        for (Fruit fruit : fruitsRankedByWins) {
            System.out.println(String.format("Fruit: %s | Wins: %s", fruit.getName(), fruit.getWins()));
        }
    }

    @Getter
    @Setter
    static class Fruit {
        String name;
        int wins;
        public Fruit(String name) {this.name = name;}
        void addWin() {
            wins++;
        }
    }
}