2017-09-25 57 views
0

我在寫LINQ表達式面臨的問題。 我想過濾下列列表(包和規則)的規則,但我得到的結果是不正確的。 請幫我改寫下面提到的預期結果的表達式。不正確的LINQ表達

public class Package 
{ 
    public int Id {get;set;} 
    public string PackageKey {get;set;} 
} 

public class Rule 
{ 
    public string Key1 {get;set;} 
    public string Key2 {get;set;} 
} 

public Class RuleEntity 
{ 
    public List<string> Keys {get;set;} 
} 

var rules = new List<Rule> 
{ 
    new Rule 
    { 
     Key1 = "001", 
     Key2 = "002", 
    }, 
    new Rule 
    { 
     Key1 = "001", 
     Key2 = "003", 
    }, 
    new Rule 
    { 
     Key1 = "004", 
     Key2 = "005", 
    }, 
    new Rule 
    { 
     Key1 = "006", 
     Key2 = "008", 
    } 
}; 

var packages = new List<Package> 
{ 
    new Package 
    { 
     Id = 1, 
     PackageKey = 001 
    }, 
    new Package 
    { 
     Id = 1, 
     PackageKey = 002 
    } 
}; 

var filteredRules = new List<RuleEntity>(); 

filteredRules.AddRange(packages.SelectMany(p => rules.Where(r => p.PackageKey.Equals(r.Key1) || p.PackageKey.Equals(r.Key2)) 
      .Select(r => new RuleEntity{ Keys = new List<string>{r.Key1, r.Key2}}) 
)); 


//Result from above expression is this. 
filteredRules 
{ 
    Keys{ "001", "002" }, 
    Keys{ "001", "003" } 
} 


//Result Expected is : 
filteredRules 
{ 
    Keys{ "001", "002" } 
} 

FilteredRules應該只包含其密鑰位於包列表中的規則。如果軟件包列表中只有一個軟件包,則在filteredRules中應該沒有規則。

+0

你只需要規則,其中的一個HashSet兩個鍵都在包列表中? – LiverpoolOwen

+0

如果一個規則與包的右邊有相同的'Key1'和'Key2',那麼你仍然會得到一個包的結果?除非這種情況從未發生過。 – juharr

回答

4

我相信這是你想要的。

rules.Where(r => packages.Any(p => p.PackageKey == r.Key1) 
      && packages.Any(p => p.PackageKey == r.Key2)) 
    .Select(r => new RuleEntity 
     { 
      Keys = new List<string> 
      { 
       r.Key1, 
       r.Key2 
      } 
     }); 

但它會更好,有前期做出查找更快的按鍵

var keys = new HashSet<string>(packages.Select(p => p.PackageKey)); 

然後Where減少到

Where(r => keys.Contains(r.Key1) && keys.Contains(r.Key2)) 
+0

使用哈希集效率的好主意。 – Chris

3

SelectMany似乎是在複雜的事情。你是想從那裏過濾規則,以便與該開始走:

rules.Where(x=>packages.Any(y=>y.PackageKey==x.Key1) && packages.Any(y=>y.PackageKey==x.Key2)); 

這將返回key1的地方有一個比賽在你的包列表和密鑰key2也有你的包列表匹配任何規則。