Пример #1
0
        public SuggestResponseDto[] SuggestForV2(int id, int limit, string key, string value)
        {
            var accounts = _repo.Accounts;


            var uniqueLikesOfTarget = accounts[id].GetLikesFrom().ToHashSet();

            ISuggestFilter filter = null;

            if (key != null)
            {
                filter = _factory.CreateFilter(key, value);
                if (filter == null)
                {
                    return(new SuggestResponseDto[0]);
                }
            }

            var likersData = SimilarityDictionaryPool.Rent();

            foreach (var likeeId in uniqueLikesOfTarget)
            {
                long targetTsSum   = 0;
                long targetTsCount = 0;

                var likersOfTargetLike = accounts[likeeId].GetLikesToWithTs();
                var l = likersOfTargetLike.GetLength(0);
                for (int i = 0; i < l; i++)
                {
                    var likerId = likersOfTargetLike[i, 0];
                    var ts      = likersOfTargetLike[i, 1];

                    if (likerId == id)
                    {
                        targetTsCount++;
                        targetTsSum += ts;
                    }
                    else if (filter == null || filter.IsOk(likerId))
                    {
                        if (!likersData.ContainsKey(likerId))
                        {
                            likersData[likerId] = CounterPool.Rent();
                        }

                        likersData[likerId].AddTs(ts);
                    }
                }

                var targetTs = (double)(targetTsSum / targetTsCount);
                foreach (var counter in likersData.Values)
                {
                    counter.Calculate(targetTs);
                }
            }


            if (likersData.Count == 0)
            {
                return(new SuggestResponseDto[0]);
            }

            var count = likersData.Count;
            var sortedIdsBySimilarity = Pool.Rent(count);

            var index = 0;

            foreach (var pair in likersData)
            {
                sortedIdsBySimilarity[index] = pair;
                index++;
            }

            Array.Sort(sortedIdsBySimilarity, 0, count, DescSimilarityComparer);

            var allExceptLikes = new List <int>();

            for (int i = 0; i < count; i++)
            {
                var likesFromCurrent = accounts[sortedIdsBySimilarity[i].Key].GetLikesFrom();
                Array.Sort(likesFromCurrent, _descComparer);

                foreach (var like in likesFromCurrent)
                {
                    if (!uniqueLikesOfTarget.Contains(like))
                    {
                        allExceptLikes.Add(like);
                        uniqueLikesOfTarget.Add(like);
                    }
                }

                if (allExceptLikes.Count >= limit)
                {
                    break;
                }
            }

            Pool.Return(sortedIdsBySimilarity);
            CounterPool.Return(sortedIdsBySimilarity.Take(count).Select(x => x.Value));
            SimilarityDictionaryPool.Return(likersData);

            return(allExceptLikes.Take(limit).Select(x => _converter.Convert(x)).ToArray());
        }