2017-08-03 6 views
1

私は購入者の名前で検索するすべての請求書を検索しようとしています。それを行う最もクリーンな方法を探しています。 私は買い手のリストを持っています。C#LINQ。オブジェクト名のプロパティまたは名前の部分でオブジェクトを検索する

List <Buyer> AllBuyers; 

と買い手がある:

public class Buyer 
    { 
     public string BuyerIdentifier{ get; set; } 
     public string Name { get; set; } 
    } 

私はバイヤーに請求書のリストを持っています。

List <Invoice> AllInvoices; 

はと請求書は、私が現在やっている何を

public class Invoice 
    { 
     public string InvoiceID { get; set; } 
     public string BuyerID { get; set; } 
     public string Amount{ get; set; } 
    } 

です:

List<string> BuyerIDs = new List<string> { }; 
foreach (Invoice inv in AllInvoices) 
{ 
    if (!(BuyerIDs.Contains(inv.BuyerID))) 
    { 
     // add BuyerID to list if it's not already there. Getting id's that are present on invoices and whose Buyer names match using contains or equals 
     BuyerIDs.Add(AllBuyers.First(b => b.BuyerIdentifier == inv.BuyerID 
      && (b.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0)).BuyerIdentifier); 
    }             
} 
Invoices = AllInvoices.FindAll(i=> BuyerIDs.Contains(i.BuyerID)); 

LINQクエリ構文は私が参加するLINQのメソッドよりも理解するのが少し楽です。だから、下の回答の後、私は今、これをやっている:

ここ
Invoices = (from buyer in AllBuyers 
       join invoice in AllInvoices on buyer.BuyerIdentifier equals invoice.BuyerID 
       where buyer.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0         
       select invoice).ToList(); 
+2

はあなたのコードの仕事をしていますか?もしあなたがコードを改善しようとしているのであれば、この質問はおそらく[Code Review Stack Exchange](https://codereview.stackexchange.com/)にあります。それ以外の場合は、どのような問題がありますか、どのようなエラーが表示されますか? –

+0

それは動作します、私はちょうどforeachループとif条件なしでそれをするLINQでより良い方法があるのだろうかと思います。 – Razkar

+0

私は何をしているのかわかりませんが、おそらく参加しているだけでしょう –

答えて

1

は、私がキーとしてBuyerIdentifierと辞書と値として請求書のリストを作成する提案です:

var dict = AllBuyers.ToDictionary(k => k.BuyerIdentifier, 
       v => AllInvoices.Where(i => i.BuyerID == v.BuyerIdentifier).ToList()); 

次にあなたがアクセスすることができますそのような具体的な買い手のための請求書のリスト:

List<Invoice> buyerInvoices = dict[buyerId]; 
+3

これはひどく非効率です。 – Iucounu

0

これはあなたのために働く必要があります。

var InvoiceGrouping = AllInvoices.GroupBy(invoice => invoice.BuyerID) 
           .Where(grouping => AllBuyers.Any(buyer => buyer.BuyerIdentifier == grouping.Key && buyer.Name.IndexOf(pair.Value, StringComparison.OrdinalIgnoreCase) >= 0)); 

最終的には、買い手のIDをキーとし、すべての請求書を値として持つグループ分けが行われます。

あなたが請求書のちょうどフラットなリストが必要な場合は、そのように行うことができます。

var Invoices = AllInvoices.GroupBy(invoice => invoice.BuyerID) 
          .Where(grouping => AllBuyers.Any(buyer => buyer.BuyerIdentifier == grouping.Key && buyer.Name.IndexOf(pair.Value, StringComparison.OrdinalIgnoreCase) >= 0)) 
          .SelectMany(grouping => grouping); 

IGrouping道具IEnumerableいるので、値の単一の列挙にグループ分けを平らに、最後に追加SelectManyを。

2

あなたが必要とするすべての請求書であれば、あなたはあなたにもバイヤーをしたい場合は、単に.Select(a => a.Invoice)を残して、あなたの2つのコレクション、フィルターに参加し、請求書

AllBuyers.Join(AllInvoices, 
      a => a.BuyerIdentifier, 
      a => a.BuyerID, 
      (b, i) => new { Buyer = b, Invoice = i }) 
    .Where(a => a.Buyer.Name.Contains("name")) 
    .Select(a => a.Invoice).ToList(); 

を選択することができます。 Contains文字列のメソッドは、equalsも同様に一致します。

+0

ありがとう、私は私が探していたものだと思う。 Containsについては、大文字と小文字を区別しない検索が欲しかったし、toLower()を使いたくなかった。 – Razkar

+1

私はあなたが参加を実行する前に買い手をフィルタリングすることで恩恵を受けると思います。私はOPが彼の最後の編集後に意図しているものだと思う。つまり、彼は名前の検索値でバイヤーをフィルターに掛けるつもりです(バイヤーの完全なリストを大幅に減らす可能性があります) –

+0

リスト内のすべてのバイヤーを1回だけ保証することはできません結果に重複した請求書があります。 –

0

ILookupおたくのように、これは私のアプローチのようになります。

var buyerMap = AllBuyers 
    .Where(b => b.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0) 
    .ToDictionary(b => b.BuyerIdentifier); 

var invoiceLookup = AllInvoices 
    .Where(i => buyerMap.ContainsKey(i.BuyerID)) 
    .ToLookup(x => x.BuyerID); 

foreach (var invoiceGroup in invoiceLookup) 
{ 
    var buyerId = invoiceGroup.Key; 
    var buyer = buyerMap[buyerId]; 
    var invoicesForBuyer = invoiceGroup.ToList(); 

    // Do your stuff with buyer and invoicesForBuyer 
} 
+0

実際には、ルックアップは必要ありません。 'GroupBy'は十分で、おそらくよりクリーンです –

関連する問題