Пример #1
0
 /// <summary>
 /// Attempts to find the value that is associated to a particular key.
 /// </summary>
 /// <typeparam name="TKey">The type of the key.</typeparam>
 /// <typeparam name="TValue">The type of the value.</typeparam>
 /// <param name="searchable">The <see cref="IBinarySearchable{TKey, TValue}"/> to search.</param>
 /// <param name="key">The key to find.</param>
 /// <param name="valueOrDefault">Upon success, assigned to the value that is associated to the
 /// <paramref name="key"/>. Upon failure, assigned to the default <typeparamref name="TValue"/>
 /// value.</param>
 /// <param name="progressReporter"><see cref="IProgress{T}"/> that receives a <see cref="ProgressReport"/>
 /// as the search progresses. May be null, in which case progress will not be reported.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that can be used to cancel the search
 /// operation. Upon cancellation, false is returned.</param>
 /// <returns>True if the <paramref name="key"/> was found, otherwise false. False indicates that the
 /// <paramref name="key"/> was not present in this <see cref="IBinarySearchable{TKey, TValue}"/>, or that
 /// the search was cancelled via the <paramref name="cancellationToken"/>.</returns>
 /// <seealso cref="TryFindIndex{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out long, IProgress{ProgressReport}, CancellationToken)"/>
 /// <seealso cref="IBinarySearchable{TKey, TValue}.GetValueAt(long)"/>
 /// <seealso cref="TryFindCeiling{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out long, out TKey, IProgress{ProgressReport}, CancellationToken)"/>
 /// <seealso cref="TryFindFloor{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out long, out TKey, IProgress{ProgressReport}, CancellationToken)"/>
 public static bool TryFindValue <TKey, TValue>(this IBinarySearchable <TKey, TValue> searchable, TKey key, out TValue valueOrDefault, IProgress <ProgressReport> progressReporter = null, CancellationToken cancellationToken = default(CancellationToken)) where TKey : IComparable <TKey>
 {
     if (TryFindIndex(searchable, key, out long index, progressReporter, cancellationToken))
     {
         valueOrDefault = searchable.GetValueAt(index);
         return(true);
     }
Пример #2
0
        /// <summary>
        /// Attempts to find the index of a particular key.
        /// </summary>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="searchable">The <see cref="IBinarySearchable{TKey, TValue}"/> to search.</param>
        /// <param name="key">The key to find.</param>
        /// <param name="index">Upon success, assigned to the index where the <paramref name="key"/> was found.
        /// Upon failure, assigned to -1.</param>
        /// <param name="progressReporter"><see cref="IProgress{T}"/> that receives a <see cref="ProgressReport"/>
        /// as the search progresses. May be null, in which case progress will not be reported.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that can be used to cancel the search
        /// operation. Upon cancellation, false is returned.</param>
        /// <returns>True if the <paramref name="key"/> was found, otherwise false. False indicates that the
        /// <paramref name="key"/> was not present in this <see cref="IBinarySearchable{TKey, TValue}"/>, or that
        /// the search was cancelled via the <paramref name="cancellationToken"/>.</returns>
        /// <seealso cref="TryFindValue{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out TValue, IProgress{ProgressReport}, CancellationToken)"/>
        /// <seealso cref="IBinarySearchable{TKey, TValue}.GetValueAt(long)"/>
        /// <seealso cref="TryFindCeiling{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out long, out TKey, IProgress{ProgressReport}, CancellationToken)"/>
        /// <seealso cref="TryFindFloor{TKey, TValue}(IBinarySearchable{TKey, TValue}, TKey, out long, out TKey, IProgress{ProgressReport}, CancellationToken)"/>
        public static bool TryFindIndex <TKey, TValue>(this IBinarySearchable <TKey, TValue> searchable, TKey key, out long index, IProgress <ProgressReport> progressReporter = null, CancellationToken cancellationToken = default(CancellationToken)) where TKey : IComparable <TKey>
        {
            if (searchable == null)
            {
                throw new ArgumentNullException(nameof(searchable));
            }
            if (cancellationToken.Equals(default(CancellationToken)))
            {
                cancellationToken = new CancellationToken(false);
            }

            long start = 0, end = searchable.Count - 1;
            long currentProgress = 0, maxProgress = CalculateSearchComplexity(searchable.Count);

            while (start <= end)
            {
                long middle = start + ((end - start) / 2);

                TKey current    = searchable.GetKeyAt(middle);
                int  comparison = current.CompareTo(key);
                currentProgress++;
                progressReporter?.Report(new ProgressReport(currentProgress, maxProgress));

                if (comparison == 0)
                {
                    //Found it
                    index = middle;
                    progressReporter?.Report(new ProgressReport(maxProgress, maxProgress));
                    return(true);
                }
                else if (comparison < 0)
                {
                    start = middle + 1;
                }
                else
                {
                    end = middle - 1;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    index = -1;
                    return(false);
                }
            }

            //Not found
            progressReporter?.Report(new ProgressReport(maxProgress, maxProgress));
            index = -1;
            return(false);
        }