2017-01-31 25 views
0

注:如何从属性重要性百分比的JavaScript对象列表中选择最相关的配置文件?

我需要

我在一个项目工作具有模块应该建议零或一个配置文件(人)登录的用户。

保存在数据库中的所有简档(除了登录用户&极限100 &选择随机地)经由API(http://example.com/suggest),为JSON结果返回,并且每个简档的结构是这样的:

{ 
name: <userName>, 
age: <userAge | default 0>, 
language: <userlanguage | default en>, 
hobbies: <anArrayOfHobbies> 
} 

的OBJECTIF是建议当前登录用户的基础上,“最相关的个人资料”:

  • 属性(在我的情况下,只有年龄,语言和爱好)。

  • 该属性对登录的用户有多重要。

比方说,API返回的结果如下:

enter image description here

,我们假设登录的用户拥有此配置文件

enter image description here

此用户可以使用内部表单来搜索“最相关的配置文件”。这种形式让他/她的每个财产的重要性的重要性百分比(SUM应该等于100%)。

  • 案例1

enter image description here

我在寻找谁具有相同的年龄(最接近的一个)作为我的个人资料。

预期的结果是{名称: “李四”,...}

  • 案例2

enter image description here

在这种情况下,对我来说最重要的是语言。

预期的结果是{名称: “简·罗伊”,...}

  • 案例3

enter image description here

在这种情况下,最重要的是兴趣爱好的数量与我分享个人资料

预期结果是{名称:“Jane Doe”,...}

什么已经做了

这是我已经开发了:

var Profile = { 
 
\t name: "", 
 
\t age: 0, 
 
\t language: "en", 
 
\t hobbies: [], 
 
\t 
 
\t getmostRelevantProfile: function(listOfProfiles){ 
 
\t \t var mostRelevantProfile = { 
 
\t \t \t age: {value: null, profile: null}, 
 
\t \t \t language: [], 
 
\t \t \t hobbies: [] 
 
\t \t }; 
 
\t \t listOfProfiles.forEach((profile)=>{ 
 
\t \t \t //console.info(profile); 
 
\t \t \t //No need to check profile.name 
 
\t \t \t 
 
\t \t \t //Check relevent profile.age 
 
\t \t \t var differencAgeBetweenMeAndCurrentProfile = this.age - profile.age; 
 
\t \t \t if(differencAgeBetweenMeAndCurrentProfile<0){ 
 
\t \t \t \t differencAgeBetweenMeAndCurrentProfile *= -1; 
 
\t \t \t } 
 
\t \t \t var differencAgeBetweenMeAndmostRelevantProfile = this.age - mostRelevantProfile.age.value; 
 
\t \t \t if(differencAgeBetweenMeAndmostRelevantProfile<0){ 
 
\t \t \t \t differencAgeBetweenMeAndmostRelevantProfile *= -1; 
 
\t \t \t } 
 
\t \t \t if(mostRelevantProfile.age.value === null || differencAgeBetweenMeAndCurrentProfile < differencAgeBetweenMeAndmostRelevantProfile){ 
 
\t \t \t \t mostRelevantProfile.age.value = profile.age; 
 
\t \t \t \t mostRelevantProfile.age.profile = profile; 
 
\t \t \t } 
 
\t \t \t 
 
\t \t \t 
 
\t \t \t //Check if this profile speakes the same language as me 
 
\t \t \t if(profile.language === this.language){ 
 
\t \t \t \t mostRelevantProfile.language.push(profile); 
 
\t \t \t } 
 
\t \t \t 
 
\t \t \t //Check if I'm sharing some hobbies with this profile 
 
\t \t \t if(this.hobbies.some((hobby)=>{ 
 
\t \t \t \t if(profile.hobbies.indexOf(hobby) > -1){ 
 
\t \t \t \t \t return true; 
 
\t \t \t \t } 
 
\t \t \t \t return false; 
 
\t \t \t })){ 
 
\t \t \t \t mostRelevantProfile.hobbies.push(profile); 
 
\t \t \t } 
 
\t \t \t 
 
\t \t }); 
 
\t \t 
 
\t \t //If at least one profile saved, return it 
 
\t \t if(mostRelevantProfile.age.value !== null){ 
 
\t \t \t return mostRelevantProfile; 
 
\t \t } 
 
\t \t return null; 
 
\t } 
 
} 
 

 
var me = Object.create(Profile); 
 
me.name = "John Doe"; 
 
me.age = 77; 
 
me.language = "es"; 
 
me.hobbies = ["music", "boating", "cooking", "drawing"]; 
 

 
var johnRoe = Object.create(Profile); 
 
johnRoe.name = "John Roe"; 
 
johnRoe.age = 20; 
 
johnRoe.language = "fr"; 
 
johnRoe.hobbies = ["basebal"]; 
 

 
var janeDoe = Object.create(Profile); 
 
janeDoe.name = "Jane Doe"; 
 
janeDoe.age = 43; 
 
janeDoe.language = "de"; 
 
janeDoe.hobbies = ["stronomy", "music", "drawing"]; 
 

 
var janeRoe = Object.create(Profile); 
 
janeRoe.name = "Jane Roe"; 
 
janeRoe.age = 76; 
 
janeRoe.language = "es"; 
 
janeRoe.hobbies = ["stronomy", "music", "walking"]; 
 

 
var mostRelevantProfileForMe = me.getmostRelevantProfile([johnRoe, janeDoe, janeRoe], {age: 13, language: 64, hobbies: 23}); 
 
console.info("mostRelevantProfileForMe:", mostRelevantProfileForMe);

缺什么(我的问题)

  • 我怎样才能添加重要性百分比选择正确的配置文件,然后如何过滤mostRelevantProfileForMe只保留“正确的”配置文件?有没有更好的方法来完成这项任务?
+0

为什么不使用一组定义百分比的数组?例如Age_Difference = {0:100%,1:99%,2:98};等等,然后在其他方面做类似的事情,那么你需要做的就是统计和引用数组?并为业余爱好,设置每个爱好的百分比重要性数组,计算总数,然后得分,然后创建您的百分比... – krisph

+0

我不完全需要百分比在这里? “_对我而言最重要的是...... _”可以通过选择重要性顺序来完成:1. ...,2. ...,3. ... - 百分比如何影响选择如果我已经设置了90%的语言?无论语言是否匹配... – Andreas

+0

@andreas当我设置语言为90%,并有2个配置文件。第一个和我说同一种语言,第二个和我的年龄相同,他们两个都没有发现爱好。结果应该是第一个配置文件,因为90% –

回答

2

的主要问题我看到存在forEach方法,它不种种变化到外部物体,并且不是所有的那些是一致的(像推匹配的语言到数组中,看起来像一个错误我)。

我会以不同的方式解决问题。首先,它看起来像要根据评分系统对可能的比赛进行排名(即排序)。那么,为什么不使用Array.sort这是非常合适的工作。

然后我们需要评分算法,它需要对每个匹配的三个不同属性进行评分,然后根据预定义的偏差对每个属性进行缩放,然后将这三个值组合在一起,比如通过对这些值进行平均。

由于我不喜欢访问/修改超出其直接范围的对象的方法,请查看我们是否可以构建构成评分函数的内容,然后将其传递以评估匹配。

这里是一个可能的实现:

var me = {}; 
 
me.name = "John Doe"; 
 
me.age = 39; 
 
me.language = "es"; 
 
me.hobbies = ["music", "boating", "cooking", "drawing"]; 
 

 
var johnRoe = {}; 
 
johnRoe.name = "John Roe"; 
 
johnRoe.age = 20; 
 
johnRoe.language = "fr"; 
 
johnRoe.hobbies = ["basebal"]; 
 

 
var janeDoe = {}; 
 
janeDoe.name = "Jane Doe"; 
 
janeDoe.age = 43; 
 
janeDoe.language = "de"; 
 
janeDoe.hobbies = ["stronomy", "music", "drawing"]; 
 

 
var janeRoe = {}; 
 
janeRoe.name = "Jane Roe"; 
 
janeRoe.age = 76; 
 
janeRoe.language = "es"; 
 
janeRoe.hobbies = ["stronomy", "music", "walking"]; 
 

 
// helper functions for the scoring system  
 

 
function getAgeScore(target, match) { 
 
    // return value in range [0,1] with 1 when same age 
 
    return 1/(1 + Math.abs(target.age - match.age)) 
 
} 
 

 
function getLanguageScore(target, match) { 
 
    // 1 if same language, 0 if different 
 
    return target.language == match.language 
 
} 
 

 
function getHobbiesScore(target, match) { 
 
    // scores in range [0,1] based on how many matching hobbies 
 
    return target.hobbies.reduce((count, hobby) => count + match.hobbies.indexOf(hobby) > 0, 0)/target.hobbies.length 
 
} 
 

 
function getScaledScoring(target, bias) { 
 
    return function(match) { 
 
    var ageScore = getAgeScore(target, match) * bias.age/100 
 
    var languageScore = getLanguageScore(target, match) * bias.language/100 
 
    var hobbyScore = getHobbiesScore(target, match) * bias.hobbies/100 
 
    return (ageScore + languageScore + hobbyScore)/3 
 
    } 
 
} 
 

 
function findBest(profiles, matcher) { 
 
    if (profiles == null) return null 
 
    var copy = profiles.slice(); // don't want to change the original list 
 
    copy.sort(function(a, b) { 
 
    return matcher(b) - matcher(a); 
 
    }) 
 
    return copy[0] // get the first one ie. the best 
 
} 
 

 
var bias = { 
 
    age: 3, 
 
    language: 8, 
 
    hobbies: 89 
 
} 
 
var matcher = getScaledScoring(me, bias) // generates the scoring method based on myself and the bias object 
 

 
var best = findBest([johnRoe, janeDoe, janeRoe], matcher) 
 

 
console.log("find best match for", me) 
 
console.log("using bias", bias) 
 
console.log("Result:", best)

注:我从在继承等长期的原始代码的一些变化,只是更简单地跟随


奖励建议:

无论距离参考点有多远(me),使用排序可以保证至少会有一次匹配。

如果您希望只有匹配得分高于某个分数,您可以将sort替换为filter,并添加阈值参数以清除某个分数下的配置文件。

+0

好的答案!谢谢。 –

相关问题