基于对象属性从列表中选择对象的算法

时间:2015-07-27 18:41:05

标签: java arrays list sorting object

有一个对象,Cars,定义为,

class Cars{
      String make;
      String model;
      String year;
....
}

对象的一些限制:

  1. 品牌,型号和年份可以带来任何价值。

  2. 不能有两个具有相同属性集的对象。例如,不能car1 = { make : "Audi", model : "A6", year : "2008" }car2 = { make : "Audi", model : "A6", year : "2008"}

  3. 让我们说我和一个服务人员谈话,该服务给我一份所有汽车对象的清单。我有一个输入(品牌,型号,年份)。我的工作是从列表中选择汽车对象(由服务返回)。我应该这样做,以便我选择匹配尽可能多的属性的对象。

    让我举个例子。让我们假设我从服务中获得了5辆车的清单,

    car1 = { make : "",     model : "A6", year : "2008" }
    car2 = { make : "Audi", model : "",   year : "2008" }
    car3 = { make : "Audi", model : "A6", year : "" }
    car4 = { make : "",     model : "",   year : "" }
    car5 = { make : "BMW",  model : "M3", year : "2009" }
    

    如果我的输入是

    {make : "Audi", model : "A6", year : "2008"}
    

    我应该可以从列表中选择一辆车。如果相同数量的参数匹配,我应该在订单make>中给出优先权。 &model;年。在上面的例子中,我应该选择car3。

    此外,如果我的输入是

    { make : "Mercedes", model : "C300", year : "2008" }
    

    我应该选择car4 = { make : "", model : "", year : "" }(通用的)

    有关解决此问题和/或伪代码的任何建议吗?

4 个答案:

答案 0 :(得分:1)

我会考虑使用数据库表来存储这些条目:

SELECT * FROM cars
WHERE make  IN('Audi', '')
AND   model IN('A6',   '')
AND   year  IN('2008', '')
SORT BY make DESC, model DESC, year DESC
LIMIT 1

然后,您可以使用SQL语句选择最佳条目:

DESC

''是因为否则LIMIT 1将首先出现。

{make : "Audi", model : "A6", year : "2008"}是根据您的排序顺序从行中选择最佳候选者。

案例1: | make | model | year | +--------+---------+------+ | Audi | A6 | '' | <--- LIMIT 1 selects this one | Audi | '' | 2008 | | '' | A6 | 2008 | | '' | '' | '' |

{ make : "Mercedes", model : "C300", year : "2008" }

案例2: | make | model | year | +--------+---------+------+ | '' | '' | '' | <---- LIMIT 1 selects this one

e.preventDefault();

答案 1 :(得分:1)

步骤1)找到符合任何条件的所有项目。

步骤2)按照将您的标准按重要性排列的分数对结果进行排序。

这是JavaScript中的一些伪代码(您可以将其迁移到Java)。

var list = [
    {a: "a1", b: "b1", c: "c1"},
    {a: "a1", b: "b1", c: "c2"},
    {a: "a1", b: "b2", c: "c1"},
    {a: "a1", b: "b2", c: "c2"},
    {a: "a2", b: "b1", c: "c1"},
    {a: "a2", b: "b1", c: "c2"},
    {a: "a2", b: "b2", c: "c1"},
    {a: "a2", b: "b2", c: "c2"}
];

function findAny(a, b, c) {
    // get a list of all of the items that match any case
    var found = list.filter(function(record) {
        return record.a == a || record.b == b || record.c == c;
    });
    // sort the items be the calculated score high to low
    function score(record) {
        var score = 0;
        if(record.a == a) { score += Math.pow(2, 2); }
        if(record.b == b) { score += Math.pow(2, 1); }
        if(record.c == c) { score += Math.pow(2, 0); }
        // setting the score on the record for education
        record.score = score;
        return score;
    }
    return found.sort(function(a, b) { return score(b) - score(a); });
}

var result = findAny("a2", "b2", "c2");
console.log(JSON.stringify(result, null, "\t"));

上述结果将是

[
    {
        "a": "a2",
        "b": "b2",
        "c": "c2",
        "score": 7
    },
    {
        "a": "a2",
        "b": "b2",
        "c": "c1",
        "score": 6
    },
    {
        "a": "a2",
        "b": "b1",
        "c": "c2",
        "score": 5
    },
    {
        "a": "a2",
        "b": "b1",
        "c": "c1",
        "score": 4
    },
    {
        "a": "a1",
        "b": "b2",
        "c": "c2",
        "score": 3
    },
    {
        "a": "a1",
        "b": "b2",
        "c": "c1",
        "score": 2
    },
    {
        "a": "a1",
        "b": "b1",
        "c": "c2",
        "score": 1
    }
]

编辑如果您只想获得得分最高的结果。

function findAnyBest(a, b, c) {
    function score(record) {
        var score = 0;
        if(record.a == a) { score += Math.pow(2, 2); }
        if(record.b == b) { score += Math.pow(2, 1); }
        if(record.c == c) { score += Math.pow(2, 0); }
        return score;
    }
    var highScore = 0;
    var found = [];
    list.forEach(function(record) {
        var currentScore = score(record);
        if(currentScore > highScore) {
            // new high score throw out the old ones
            found = [record];
            highScore = currentScore;
        } else if(currentScore === highScore) {
            found.push(record);
        }
    });
    return found;
}

答案 2 :(得分:1)

请注意,我们不需要在此处进行任何排序,只需找到最高分数即可。排序会使您的解决方案O(NlogN),而找到最大值为O(N)

public Car getBestSelection(List<Car> cars, String make, String model, String year){
    Map<Car, Integer> scoreMap = new HashMap<>(cars.size());

    // Find scores for all valid cars
    for(Car car : cars)
        if(isValidCar(car, make, model, year))
            scoreMap.push(car, calcScore(car, make, model, year));

    // find max score
    Car maxCar;
    int maxScore;
    for(Map.Entry<Car, Integer> e : scoreMap.entrySet()){
        if(e.getValue() > maxScore){
            maxScore = e.getValue();
            maxCar = e.getKey();
        }
    }

    return maxCar;
}

public int calcScore(Car car, String make, String model, String year){
    int makeScore  = car.make.equals(make)   ? Math.pow(2,2) : 0;
    int modelScore = car.model.equals(model) ? Math.pow(2,1) : 0;
    int yearScore  = car.year.equals(year)   ? Math.pow(2,0) : 0;

    return makeScore + modelScore + yearScore;
}

public boolean isValidCar(Car car, String make, String model, String year){
    return (car.make.equals("") && car.model.equals("") && car.year.equals("")) ||
           (car.make.equals(make) || car.model.equals(model) || car.year.equals(year));
}

答案 3 :(得分:0)

上述答案大多是正确的,但实际上并没有解决问题。当使用指数模型来确定汽车匹配的程度时,最高匹配将始终获胜。这意味着单独制作匹配(4分)的得分高于模型和年份的匹配(2 + 1 = 3分)。这与初步问题的评论相反应该发生。

最好使用线性模型(例如,make = 4 points,model = 3 points,year = 2 points)。这样,匹配任何两个标准都将胜过匹配单个标准。