2017-05-30 80 views
5

我有一個字符串,其中每個項目是描述一個技能自由文本的列表,所以看起來有點像這樣:
搜索字符串中包含數組字典鍵

List<string> list = new List<string> {"very good right now", "pretty good", 
"convinced me that is good", "pretty medium", "just medium" .....} 

而且我想保持一個用戶這些自由文本的分數。所以現在,我使用條件:

foreach (var item in list) 
     { 
      if (item.Contains("good")) 
      { 
       score += 2.5; 
       Console.WriteLine("good skill, score+= 2.5, is now {0}", score); 
      } 
      else if (item.Contains(low")) 
      { 
       score += 1.0; 
       Console.WriteLine("low skill, score+= 1.0, is now {0}", score); 
      } 

     } 

假設在furure我想用字典比分映射,如:

Dictionary<string, double> dic = new Dictionary<string, double> 
{ { "good", 2.5 }, { "low", 1.0 }}; 

會是什麼之間跨越的好方法字典值和字符串列表?我現在看到的方式是做一個嵌套循環:

foreach (var item in list) 
     { 
      foreach (var key in dic.Keys) 
       if (item.Contains(key)) 
        score += dic[key]; 
     } 

但我敢肯定有更好的方法。最好至少快一點,或者更好看一些(LINQ)。

謝謝。

+0

我懷疑你能做到這一點得更快,因爲大多數其他方式(LINQ與否)可能會做嵌套在幕後循環。另外,除非你擁有數千種技能,否則性能差異可能會忽略不計。恕我直言,你提出的解決方案是不是不愉快的眼睛:) – HaukurHaf

+0

「好運讓這個小丑做任何有用的事情」 - >「好」和「有用」。也就是說,你的設計對我來說看起來很合理,我希望在下一次的表現評估中獲得好處。 –

+0

請注意,使用字典的方法與您的原始方法不同,因爲您在詞典 –

回答

2
var scores = from item in list 
      from word in item.Split() 
      join kvp in dic on word equals kvp.Key 
      select kvp.Value; 

var totalScore = scores.Sum(); 

注意:您當前的解決方案檢查列表中的項目是否包含字典中的鍵。但即使字典中的關鍵字是該項目中某個單詞的一部分,它也會返回true。例如。 "follow the rabbit"包含"low"。將項目拆分成單詞解決了這個問題。

也LINQ連接內部使用哈希集來搜索第二個序列中的第一個序列項。當你枚舉字典的所有條目時,這給你O(1)查找速度而不是O(N)。

+1

中爲每個鍵添加分數我更喜歡這一個,因爲您還啓發了關於分詞的啓示。但是,我不熟悉那種語法。這是否也被視爲LINQ? –

+0

@yoadw是的,這是用*查詢語法編寫的LINQ *(語言集成的語法) –

1

它真的不是更快,但你可以使用LINQ:

score = list.Select(s => dic.Where(d => s.Contains(d.Key)) 
      .Sum(d => d.Value)) 
      .Sum(); 

請注意,例如循環將達到2個不同的密鑰,如果他字符串匹配兩者,我一直在我的解決方案。

2

如果您的代碼發現包含單詞「good」的技能字符串,則它將得分2.5 N次。

因此,您可以只計算包含字典工作的技能字符串,並將相應分數上的值相乘。

var scores = from pair in dic 
      let word = pair.Key 
      let score = pair.Value 
      let count = list.Count(x => x.Contains(word)) 
      select score * count; 

var totalScore = scores.Sum(); 
0

好了,你是不是真的使用字典作爲字典,所以我們可以這樣簡化了一下用新的類:

class TermValue 
{ 
    public string Term { get; set; } 
    public double Value { get; set; } 

    public TermValue(string t, double v) 
    { 
     Term = t; 
     Value = v; 
    } 
} 

這樣,我們可以更直接一點:

void Main() 
{ 
    var dic = new TermValue[] { new TermValue("good", 2.5), new TermValue("low", 1.0)}; 


    List<string> list = new List<string> {"very good right now", "pretty good", 
"convinced me that is good", "pretty medium", "just medium" }; 

    double score = 0.0; 
    foreach (var item in list) 
    { 
     var entry = dic.FirstOrDefault(d =>item.Contains(d.Term)); 
     if (entry != null) 
      score += entry.Value; 
    } 
} 

從這裏,我們可以只玩了一下(這個編譯後的代碼將可能是同上)

double score = 0.0; 
    foreach (var item in list) 
    { 
     score += dic.FirstOrDefault(d =>item.Contains(d.Term))?.Value ?? 0.0; 
    } 

然後,(在紫色的的話),我們可以去瘋狂:

double score = list.Aggregate(0.0, 
    (scre, item) =>scre + (dic.FirstOrDefault(d => item.Contains(d.Term))?.Value ?? 0.0));