2017-03-28 5 views
2

私は、製品の大きなリストから関連する製品の上位N要素を選択する必要があります。 これまでのところ、以下のコードがあり、完全に動作します。上位N個の要素を選択し、出現順を覚えてください

class Product 
{ 
    public string Name; 
    public double Rating; 
    public List<Product> RelatedProducts; 

    public List<Product> GetTopRelatedProducts(int N) 
    { 
     var relatedSet = new HashSet<Product>(); 
     var relatedListQueue = new Queue<List<Product>>(); 
     if (RelatedProducts != null && RelatedProducts.Count > 0) 
      relatedListQueue.Enqueue(RelatedProducts); 
     while (relatedListQueue.Count > 0) 
     { 
      var relatedList = relatedListQueue.Dequeue(); 
      foreach (var product in relatedList) 
      { 
       if (product != this && relatedSet.Add(product) && product.RelatedProducts != null && product.RelatedProducts.Count > 0) 
        relatedListQueue.Enqueue(product.RelatedProducts); 
      } 
     } 
     return relatedSet.OrderByDescending(x => x.Rating).Take(N).OrderBy(/*How to order by occurrence here? */).ToList(); 
    } 
} 

は今、私はGetTopRelatedProducts方法は、トップN品の発生順序を覚えておきたいです。 HashSetに最初に追加された商品は、返されたリストの最初になります。例えば

、私はこのシナリオを持っている場合:

//... 
relatedSet.Add(new Product(){Name="A", Rating=3}); 
relatedSet.Add(new Product(){Name="B", Rating=4}); 
relatedSet.Add(new Product(){Name="C", Rating=5}); 
//... 

N = 2場合

は、この方法は、返すべき: B,C代わりに C,B Bため、最初 HashSetに添加しました。

 var relatedSetCopy = relatedSet.ToList(); 
     return (from p in relatedSet.OrderByDescending(x => x.Rate).Take(N) 
        join c in relatedSetCopy on p.Name equals c.Name 
        let index = relatedSetCopy.IndexOf(c) 
        orderby index 
        select p).ToList(); 

は基本的に、私はそれがRating上ご注文前だったのと同じ方法でリストを順序し直すLINQ Joinを使用します。

は、だから私はにメソッドにreturn文を変更しました。

最初に追加した商品は他の商品よりも選択した商品との類似性が高いので、この方法でやりたいと思います。

私はここに二つの質問があります。

  1. は、再注文返されたリストに良い方法はありますか?
  2. 製品間の関係を処理する優れた設計はありますか? (私は、ツリー構造の実装を考えていた。オブジェクトのナビゲーションと検索がより速くなるでしょう。だから)

答えて

3

返されたリストをオーダーし直すためのより良い方法はありますか?トップN関連の並べ替えセットで

あなたはできるだけでIntersectrelatedSetIntersectは、第1の配列内の順序に基づいてアイテムを生成するため。

ので、代わりの

return relatedSet.OrderByDescending(x => x.Rating).Take(N).ToList(); 

あなたは

return relatedSet.Intersect(relatedSet.OrderByDescending(x => x.Rating).Take(N)).ToList(); 
+0

良いアイデアを使用します!!! 2番目の質問に対する提案はありますか? – Mhd

+0

2番目の質問には簡単な答えはありません。このような構造をデータベースに保持しているのであれば、おそらくそれを実行した方法が唯一可能な方法です。しかし、あるソースからメモリ構造だけを構築している場合、おそらく共有された 'HashSet'を(処理中にビルドしたものに似ていますが、' this'も含めて)各製品に格納することができますより良い。 –

関連する問題