2010-04-21 42 views
10

Hãy xem câu hỏi của tôi HERE, bây giờ tôi muốn trả lại đề xuất tiếp theo đối tượng (sau) đối sánh phù hợp với tiêu chí.LINQ Mục tiếp theo trong Danh sách

Vì vậy, nói rằng tôi đã tìm thấy mục 6 trong số 10, tôi muốn truy vấn trả lại mục 7 thay thế.

Hoặc có cách nào tốt hơn không?

Trả lời

14

Vì bạn có một đối tượng List<T> bạn có thể sử dụng phương pháp FindIndex của nó thay vì Where để có được những chỉ số của mặt hàng đó phù hợp đầu tiên chứ không phải là mục riêng của mình:

int index = recommendations.FindIndex(rp => 
              rp.Products.Any(p => p.Product.Code == "A") 
             && rp.Products.Any(p => p.Product.Code == "B") 
            ); 

Một khi bạn có chỉ số bạn có thể nhận được mục tiếp theo hoặc mục trước hoặc bất kỳ thứ gì bạn muốn.

+0

+1 Để sử dụng cú pháp lambda. –

0

Mục 7 có phù hợp với mệnh đề Where của bạn không? Nếu vậy, sử dụng các phương pháp Skip()Take() mở rộng:

var myProducts = 
    from rp in recommendations 
    where 
     cp.Products.Any(p => p.Product.Code == "A") && 
     cp.Products.Any(p => p.Product.Code == "B") 
    select rp; 

var nextProduct = myProducts.Skip(1).Take(1); 
+0

Tôi không nghĩ rằng điều này sẽ làm việc chính xác. Trong trường hợp OPs có vẻ như bản gốc sẽ chỉ trả lại 1 kết quả, và họ muốn tiếp theo trong danh sách ORIGINAL. –

+0

@ spoulson, đúng vậy. Tôi muốn tìm mục phù hợp và sau đó trả lại mục tiếp theo trong danh sách. – griegs

1

này nên làm điều đó. Tôi đã không xây dựng một thử nghiệm cho nó cụ thể.

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        on item1.Index equals item2.Index - 1 
        where item1.Rec.Products.Any(p => p.Code == "A") 
        && item1.Rec.Products.Any(p => p.Code == "B") 
        select item2.Rec; 

Nếu bạn cần cả hai hồ sơ, báo cáo kết quả lựa chọn có thể là

select new { MatchingItem = item1.Rec, NextItem = item2.Rec }; 

Nhưng sau đó bạn sẽ phải làm một nhóm để giải thích cho một mục phù hợp là mục cuối cùng trong danh sách (có sẽ không phải là một mục tiếp theo trong trường hợp đó).

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        on item1.Index equals item2.Index - 1 
        into groupjoin 
        from i2 in groupjoin.DefaultIfEmpty() 
        where item1.Rec.Products.Any(p => p.Code == "A") 
        && item1.Rec.Products.Any(p => p.Code == "B") 
        select new { MatchingItem = item1.Rec, NextItem = i2 == null ? null : i2.Rec }; 

Mã I đã làm kiểm tra tương tự với danh sách chuỗi.

List<string> list = new List<string>() { "a", "b", "c", "a", "d", "a", "e" }; 

var query = from item1 in list.Select((s, idx) => new { Item = s, Index = idx }) 
      join item2 in list.Select((s, idx) => new { Item = s, Index = idx }) 
      on item1.Index equals item2.Index - 1 
      where item1.Item == "a" 
      select item2.Item; 

Trả về b, d và e.

28

Dưới đây là phương pháp tốt nhất hiện tại của tôi:

MyList.SkipWhile(item => item.Name != "someName").Skip(1).FirstOrDefault() 

Một câu trả lời trước đó sử dụng Skip(1).Take(1) mà làm việc, nhưng trả về một danh sách của một kết quả. Trong trường hợp của tôi (và có lẽ là trường hợp của OP), chúng tôi đang tìm kiếm các mặt hàng thực tế. Vì vậy, mã của tôi bỏ qua cho đến khi nó được một trong những chúng tôi đang tìm kiếm (một nơi sẽ trở về một tập hợp con để chúng tôi sẽ không có quyền truy cập vào mục tiếp theo) sau đó bỏ qua một và sau đó nhận được các mục.

+0

Lưu ý: Câu trả lời này được đề cập trong khóa học Microsoft Virtual Academy 'De-Mystifying LINQ' - Phần 6 –

4

Làm thế nào về một cái gì đó như thế này:

public static class Extension 
{ 
    public static T Next<T>(this IEnumerable<T> source, Func<T, bool> predicate) 
    { 
     bool flag = false; 

     using (var enumerator = source.GetEnumerator()) 
     { 
      while (enumerator.MoveNext()) 
      { 
       if (flag) return enumerator.Current; 

       if(predicate(enumerator.Current)) 
       { 
        flag = true; 
       } 
      } 
     } 
     return default(T); 
    } 
} 

Sau đó, bạn có thể gọi nó như bạn sẽ cho đâu

Products.Next(x => x.Whatever); 
3

Hãy thử điều này một


TIẾP mục

MyList.SkipWhile(x => x != value).Skip(1).FirstOrDefault(); 

PREVIOUS mục lưu ý: Xếp() sẽ không làm việc cho LINQ to SQL

var MyList2 = MyList.ToList(); 
MyList2.Reverse(); 
MyList2.SkipWhile(x => x != value).Skip(1).FirstOrDefault(); 
+0

Tôi nghĩ rằng 'Reverse' không được triển khai trong SQL Server. –

+0

http://msdn.microsoft.com/en-us/library/bb358497(v=vs.110).aspx Đó là LINQ và Đảo ngược ở đây –

+0

Vâng, đó là LINQ API, nhưng nếu đó là LINQ to SQL (Máy chủ) , nó sẽ ném lỗi, bởi vì không có sự tương đương trong SQL. –

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