public override bool Equals(Object o)
        {
            if (!(o is GenericRecommendedItem))
            {
                return(false);
            }
            GenericRecommendedItem other = (GenericRecommendedItem)o;

            return(item.Equals(other.item) && value == other.value);
        }
Beispiel #2
0
        public static IList <RecommendedItem> GetTopItems(int howMany,
                                                          IEnumerable <Item> allItems,
                                                          Rescorer <Item> rescorer,
                                                          Estimator <Item> estimator)
        {
            if (allItems == null || rescorer == null || estimator == null)
            {
                throw new ArgumentNullException("argument is null");
            }

            LinkedList <RecommendedItem> topItems = new LinkedList <RecommendedItem>();

            bool full = false;

            foreach (Item item in allItems)
            {
                if (item.IsRecommendable && !rescorer.IsFiltered(item))
                {
                    double preference   = estimator.Estimate(item);
                    double rescoredPref = rescorer.Rescore(item, preference);
                    LinkedListNode <RecommendedItem> node = topItems.Last;

                    if (!Double.IsNaN(rescoredPref) &&
                        (!full || rescoredPref > node.Value.Value))
                    {
                        // I think this is faster than Collections.binarySearch() over a LinkedList since our
                        // comparisons are cheap, which binarySearch() economizes at the expense of more traversals.
                        // We also know that the right position tends to be at the end of the list.
                        while (node != null && node.Previous != null)
                        {
                            node = node.Previous;
                            if (rescoredPref <= node.Value.Value)
                            {
                                node = node.Next;
                                break;
                            }

                            if (node == topItems.First)
                            {
                                break;
                            }
                        }

                        RecommendedItem newItem = new GenericRecommendedItem(item, rescoredPref);

                        if (node == null)
                        {
                            topItems.AddFirst(newItem);
                        }
                        else if (topItems.Count == 1)
                        {
                            // special handling in this case is to avoid problems
                            // with negative preferences. Imagine -0.3 being added
                            // first followed by -0.6. If we simply did AddAfter,
                            // those items would be out of sequence - cc
                            if (rescoredPref > node.Value.Value)
                            {
                                topItems.AddAfter(node, newItem);
                            }
                            else
                            {
                                topItems.AddBefore(node, newItem);
                            }
                        }
                        else
                        {
                            topItems.AddAfter(node, newItem);
                        }

                        if (full)
                        {
                            topItems.RemoveLast();
                        }
                        else if (topItems.Count > howMany)
                        {
                            full = true;
                            topItems.RemoveLast();
                        }
                    }
                }
            }

            List <RecommendedItem> result = new List <RecommendedItem>(topItems.Count);

            foreach (RecommendedItem item in topItems)
            {
                result.Add(item);
            }
            return(result);
        }