2015-10-16 17 views
6

Chỉ có thể trả lại những người phù hợp với tất cả giá trị danh sách trong LINQ?Điều này có thể thực hiện được trong LINQ không?

Tôi có một bảng klist trong đó hai cột có sẵn:

Kid - Tableid 
001  1 
001  2 
002  1 
003  3 
004  1 
004  2 

và tôi có một danh sách có chứa tid giá trị:

List<int> tid = new List<int>(); 
tid.Add(1); 
tid.Add(2); 

nay là danh sách tid có 1 và 2 giá trị.

Vì vậy, câu hỏi của tôi là từ klist bảng Tôi sẽ chỉ nhận được những kid có chứa tất cả các giá trị danh sách tid và so sánh với id bảng.

Kết quả dự kiến ​​sau đây là

kid - 001 
kid - 004 

tôi đã cố gắng truy vấn dưới đây:

var lb = Klist.Where(t => tid .Contains(t.Tableid)).Select(k => k.Kid).Distinct().ToList(); 

Nhưng đó trả về tất cả các khớp nhỏ, nếu ngay cả trận đấu duy nhất sau đó họ đưa ra kết quả đó, nhưng Tôi chỉ muốn những người phù hợp với tất cả các id bảng với danh sách tid. Và kết quả của truy vấn của tôi là

kid - 001 
kid - 002 
kid - 003 
kid - 004 

Xin gợi ý cho một truy vấn LINQ cho việc này.

+0

LINQ phải không? Tôi có thể đưa ra giải pháp với truy vấn sql. – niksofteng

+0

Không, tôi muốn điều này trong LINQ – ADMIN

+0

Có thể câu trả lời này [giao nhau] (http://stackoverflow.com/a/7565274/1257607) có thể trợ giúp – DanielV

Trả lời

1

Để đạt được những gì bạn muốn, trước tiên bạn cần Group giá trị của bạn bằng cách Kid:

Klist.GroupBy(k => k.Kid) 

Kết quả là một danh sách riêng biệt Kid s với họ tương ứng Tableid s.

Sau đó, chúng tôi cần chọn các nhóm mà tất cả các nhóm của chúng là Tableid s giống với tid s. Điều này có thể đạt được bằng cách xóa các phần tử giống hệt nhau khỏi cả hai danh sách, với Except. Sau đó, chúng tôi kiểm tra xem không có phần tử còn lại nào (tức là cả hai tập hợp đều bằng nhau).

.Where(g => tid.Except(g.Select(s => s.Tableid)).Count() == 0) 

Cuối cùng, có Kid của các nhóm còn lại, được lưu trữ như Key trong nhóm:

.Select(g => g.Key); 

Nếu chúng ta tập hợp tất cả mọi thứ lại với nhau, chúng tôi nhận được truy vấn LINQ sau:

var lb = Klist.GroupBy(k => k.Kid).Where(g => tid.Except(g.Select(s => s.Tableid)).Count() == 0).Select(g => g.Key); 

trả lại các phần tử 001004

1

Bạn có thể nhóm kList đầu tiên, sau đó sử dụng SequenceEqual với tid, đây là một bản demo

List<KeyValuePair<string, int>> kList = new List<KeyValuePair<string, int>>() 
{ 
    new KeyValuePair<string, int>("001",1), 
    new KeyValuePair<string, int>("001",2), 
    new KeyValuePair<string, int>("002",1), 
    new KeyValuePair<string, int>("003",3), 
    new KeyValuePair<string, int>("004",1), 
    new KeyValuePair<string, int>("004",2) 
}; 
List<int> tid = new List<int>() { 1, 2 }; 
var query = kList.GroupBy(i => i.Key) 
    .Where(g => g.Select(j => j.Value).Distinct().OrderBy(i => i).SequenceEqual(tid)) 
    .SelectMany(g => g.Select(x => x.Key)).Distinct(); 
Console.WriteLine(string.Join(",", query)); 

và có thể SequenceEqual có một số vấn đề, nếu bạn muốn contains tất cả tid, không Equal, sau đó bạn có thể sử dụng Intersect để instand of SequenceEqual, mã này giống như thế này

List<KeyValuePair<string, int>> kList = new List<KeyValuePair<string, int>>() 
{ 
    new KeyValuePair<string, int>("001",1), 
    new KeyValuePair<string, int>("001",2), 
    new KeyValuePair<string, int>("002",1), 
    new KeyValuePair<string, int>("001",3),//special one 
    new KeyValuePair<string, int>("003",3), 
    new KeyValuePair<string, int>("004",1), 
    new KeyValuePair<string, int>("004",2) 
}; 
List<int> tid = new List<int>() { 1, 2 }; 
var query = kList.GroupBy(i => i.Key) 
    .Where(g => g.Select(j => j.Value).Distinct().Intersect(tid).Count()==tid.Count) 
    .SelectMany(g => g.Select(x => x.Key)).Distinct(); 
Console.WriteLine(string.Join(",", query)); 
0

này hoạt động khá độc đáo:

var kList = new [] 
{ 
    new { Kid = "001", Tableid = 1 }, 
    new { Kid = "001", Tableid = 2 }, 
    new { Kid = "002", Tableid = 1 }, 
    new { Kid = "003", Tableid = 3 }, 
    new { Kid = "004", Tableid = 1 }, 
    new { Kid = "004", Tableid = 2 }, 
}; 

var tid = new List<int>() { 1, 2, }; 

var lookup = kList.ToLookup(k => k.Tableid, k => k.Kid); 

này tạo ra:

1 => "001", "002", "004" 
2 => "001", "004" 
3 => "003" 

var result = tid.Select(t => lookup[t]).Aggregate((ts0, ts1) => ts0.Intersect(ts1)); 

Các tid.Select(...) sản xuất { { "001", "002", "004" }, { "001", "004" } }Aggregate sau đó thực hiện giao nhau trên hai này.

Kết quả là:

001 
004 
0

Một cách khác bạn có thể làm điều đó:

var list = kList.GroupBy(x => x.Kid) 
      .Select(group => new 
      { 
       Kid = group.FirstOrDefault().Kid, 
       gtid = group.Select(groupItem => groupItem.Tableid).ToList() 
      }) 
      .Where(group => !group.gtid.Except(tid).Any() 
       && !tid.Except(group.gtid).Any()) 
      .Select(group => group.Kid); 

Về cơ bản giống như các giải pháp khác, bạn nhóm các dữ liệu trong kList và tạo ra một danh sách mới với kid và một danh sách của Tableid 's. Và sau đó lọc danh sách mới đó bằng cách so sánh danh sách Tableid với số tid của bạn (đảm bảo rằng một danh sách không có mục danh sách không nằm trong danh sách kia và ngược lại). Sau đó, bạn chọn giá trị kid.

0

Có rất nhiều câu trả lời rằng Except(Func<T, bool>).Any() hoặc Except(Func<T, bool>).Count() == 0 nhưng cả hai kết hợp này có vẻ như chúng chỉ là All(Func<T, bool>).

Dựa trên câu hỏi của bạn, bạn nói rằng bạn chỉ muốn giá trị kid khi nó tồn tại trong All hàng cho giá trị kid đó. Đây là cách tôi sẽ làm điều đó.

var lb = klist.GroupBy(lst => lst.Kid) 
       .Where(t => tid.All(td => t.Select(x => x.TableId).Contains(td))) 
       .Select(grp => grp.Key); 

Nhóm này đưa bảng vào bộ chứa Kid. Sau đó nó lọc ra các hàng không có all giá trị tid tồn tại. Sau đó, chọn khóa cho các nhóm đó là Kid.

Các vấn đề liên quan