2012-02-03 60 views
1

我有一份玩家名單,每名玩家都有一份技能等級列表。 我想要做的是根據與特定搜索列表匹配的評分排序這些玩家。比較整數列表,然後根據相似性排序它們。

下面是四個球員的榜樣:

 List<Skill> skillsA = new List<Skill>(); 
     List<Skill> skillsB = new List<Skill>(); 
     List<Skill> skillsC = new List<Skill>(); 
     List<Skill> skillsD = new List<Skill>(); 

     skillsA.Add(new Skill() { Name = "Speed", Value = 1 }); 
     skillsA.Add(new Skill() { Name = "Agility", Value = 5 }); 
     skillsA.Add(new Skill() { Name = "Strength", Value = 3 }); 
     skillsA.Add(new Skill() { Name = "Endurance", Value = 4 }); 

     skillsB.Add(new Skill() { Name = "Speed", Value = 5 }); 
     skillsB.Add(new Skill() { Name = "Agility", Value = 2 }); 
     skillsB.Add(new Skill() { Name = "Strength", Value = 1 }); 
     skillsB.Add(new Skill() { Name = "Endurance", Value = 3 }); 

     skillsC.Add(new Skill() { Name = "Speed", Value = 5 }); 
     skillsC.Add(new Skill() { Name = "Agility", Value = 3 }); 
     skillsC.Add(new Skill() { Name = "Strength", Value = 2 }); 
     skillsC.Add(new Skill() { Name = "Endurance", Value = 2 }); 

     skillsD.Add(new Skill() { Name = "Speed", Value = 1 }); 
     skillsD.Add(new Skill() { Name = "Agility", Value = 2 }); 
     skillsD.Add(new Skill() { Name = "Strength", Value = 5 }); 
     skillsD.Add(new Skill() { Name = "Endurance", Value = 4 }); 

     Player A = new Player() { Skills = skillsA }; 
     Player B = new Player() { Skills = skillsB }; 
     Player C = new Player() { Skills = skillsC }; 
     Player D = new Player() { Skills = skillsD }; 

這將是搜索列表我比較:

 List<Skill> matchSkill = new List<Skill>(); 

     matchSkill.Add(new Skill() { Name = "Speed", Value = 5 }); 
     matchSkill.Add(new Skill() { Name = "Agility", Value = 2 }); 
     matchSkill.Add(new Skill() { Name = "Strength", Value = 1 }); 
     matchSkill.Add(new Skill() { Name = "Endurance", Value = 1 }); 

     SkillSearch SkillSearch = new SkillSearch() { Skills = matchSkill }; 

我應該回來的球員名單下令PlayerB,PlayerC,PlayerD ,玩家A

技能列表將始終是相同的大小和順序。技能總是在1-5之間。我試圖用絕對值來比較這些值之間的差異。例如,如果搜索是針對(3)2和4會比1或5

總之更接近的匹配,如果你只是看它們作爲數字數組的你將有:

 search = { 5, 2, 1, 1} 

     playerb = { 5, 2, 1, 3} : difference {0,0,0,2} (2 total) 
     playerc = { 5, 3, 2, 2} : difference {0,1,1,1} (3 total) 
     playerd = { 1, 2, 5, 4} : difference {4,0,4,3} (11 total) 
     playera = { 1, 5, 3, 4} : difference {4,3,2,3} (12 total) 

我將如何使用C#訂購這些產品?我更喜歡linq結果。我只是不確定如何得到這些訂單。

+0

對不起,由於某種原因,我忘了添加問題... – 2012-02-03 17:28:27

+1

似乎你已選擇曼哈頓距離作爲你的距離測量。那麼,問題是什麼?您需要計算兩組技能之間絕對差異的總和,並按最低距離對其進行排名。 – Andreas 2012-02-03 18:29:34

回答

3

假設類:

public class Skill 
{ 
    public string Name { get; set; } 
    public int Value { get; set; } 
} 

public class Player 
{ 
    public string Name { get; set; } 
    public ICollection<Skill> Skills { get; set; } 
} 

您可以用collection initializers取代List<T>.Add調用序列:

Player[] players = new Player[] 
{ 
    new Player 
    { 
     Name = "A", 
     Skills = new Skill[] 
     { 
      new Skill { Name = "Speed", Value = 1 }, 
      new Skill { Name = "Agility", Value = 5 }, 
      new Skill { Name = "Strength", Value = 3 }, 
      new Skill { Name = "Endurance", Value = 4 }, 
     } 
    }, 
    new Player 
    { 
     Name = "B", 
     Skills = new Skill[] 
     { 
      new Skill { Name = "Speed", Value = 5 }, 
      new Skill { Name = "Agility", Value = 2 }, 
      new Skill { Name = "Strength", Value = 1 }, 
      new Skill { Name = "Endurance", Value = 3 }, 
     } 
    }, 
    new Player 
    { 
     Name = "C", 
     Skills = new Skill[] 
     { 
      new Skill { Name = "Speed", Value = 5 }, 
      new Skill { Name = "Agility", Value = 3 }, 
      new Skill { Name = "Strength", Value = 2 }, 
      new Skill { Name = "Endurance", Value = 2 }, 
     } 
    }, 
    new Player 
    { 
     Name = "D", 
     Skills = new Skill[] 
     { 
      new Skill { Name = "Speed", Value = 1 }, 
      new Skill { Name = "Agility", Value = 2 }, 
      new Skill { Name = "Strength", Value = 5 }, 
      new Skill { Name = "Endurance", Value = 4 }, 
     } 
    } 
}; 

Skill[] matchSkills = new Skill[] 
{ 
    new Skill { Name = "Speed", Value = 5 }, 
    new Skill { Name = "Agility", Value = 2 }, 
    new Skill { Name = "Strength", Value = 1 }, 
    new Skill { Name = "Endurance", Value = 1 }, 
}; 

接下來,你應該建立在matchSkills收集Dictionary<string, Skill>;這將允許您按名稱快速查找技巧:

var matchSkillsDictionary = matchSkills.ToDictionary(matchSkill => matchSkill.Name); 

最後,你可以使用LINQ OrderBy操作你的球員在遞減的技能差總和值進行排序。我們將用兩個中間的功能,以幫助使事情變得清晰:

Func<Skill, int> getSkillDiff = skill => Math.Abs(skill.Value - matchSkillsDictionary[skill.Name].Value); 
Func<Player, int> getPlayerDiff = player => player.Skills.Sum(getSkillDiff); 
IEnumerable<Player> orderedPlayers = players.OrderBy(getPlayerDiff); 
+0

工程就像一個魅力!如果我的應用程序需要從循環中添加硬編碼(如示例),我會使用集合初始值設定項。玩家和技能最初將從實體框架結果填充。我最初的代碼會利用一個proc,但是有一個匹配的searchskills列表可以比較容易地進行比較。非常感謝。 – 2012-02-03 19:09:20

+1

使意義重新收集初始值設定項;我應該假設你不會使用硬編碼數據:-) – Douglas 2012-02-03 19:26:20

3

試試這個:

players.OrderBy(player => player.Skills.Zip(matchSkills, (pl, sr) => Math.Abs(pl.Value - sr.Value)).Sum()) 

球員是數組{A,B,C,d}。

修復了道格拉斯遺漏的「.Skills」和「.Value」部件。

+0

運算符不能應用於「Math.Abs​​(pl-sr)」?也許我沒有正確分配搜索? – 2012-02-03 19:13:09

+0

直到星期天才能檢查,所以你可以嘗試自己看看。這裏是Zip文檔:http://msdn.microsoft.com/en-us/library/dd267698.aspx。我會檢查我的答案,並會更新我的帖子。 – 2012-02-03 19:21:48

2

回覆梅德Polyanitsa:

我想這是你的意思是:

players.OrderBy(player => player.Skills.Zip(matchSkills, (pl, sr) => Math.Abs(pl.Value - sr.Value)).Sum()); 

但是,你假定所有玩家的技能(和匹配組)是總是以相同的順序。如果一個玩家定義了Speed, Agility, Strength, Endurance,另一個玩家不能定義Agility, Speed, Strength, Endurance

編輯:其實,你的假設是正確的。問題指出:「技能列表將始終是相同的大小和順序。「我很抱歉失蹤。

在這種情況下,您的解決方案可能比我的原始提案更有效,因爲它避免了名稱查找的開銷。

+0

謝謝,不知何故錯過了該部分的問題。是的,我同意你的技能順序。 – 2012-02-03 19:55:26

+0

無論如何,擁有簡單明瞭的解決方案和更加清晰可擴展的解決方案總是不錯的。 – 2012-02-03 20:36:13

相關問題