2017-01-31 70 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

好的答案!謝謝。 –

相關問題