在WPF中,我想让我的ObservableCollection保持排序。项目是随机添加的,不是批量添加的。我不想每次对整个IList进行排序。我想在每个插入物的适当位置插入。
有没有一种方法可以将项目快速(log(n))插入到T的任何IList中。
有人为它写过代码吗?
注意:是的,在调用此方法之前,列表应该已经排序。
注2:有时您必须使用IList,并且不能将其替换为SortedList,并且不想维护2个集合:例如:在WPF中使用ObservableCollection。
更新,是的,有一种方法可以做到。通过使用二分法。我问这个问题可以节省时间。我正在编写它,调试后将立即显示它。
答案 0 :(得分:1)
好的...我是在有人关闭我的问题之前完成的(这几乎要2票才能完成)...
尽管有2个人投票关闭,但我认为这是个好问题,我也认为代码值得保留。
我花了大约5个小时来进行调试。似乎工作正常。节省5个小时...这就是为什么我问这个问题。为了节省时间。
/// <summary>
/// Insert item in list in log(n). The list should already be sorted.
/// Item will be inserted and there will be duplicate if comparer return 0.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
public static int InsertInSortedList<T>(this IList<T> list, T item, Func<T, T, int> comparer = null)
{
if (comparer == null)
{
comparer = Comparer<T>.Default.Compare;
}
int first = 0;
int last = list.Count;
int middle = 0;
int compareResult = 0;
if (last > 0)
{
while (true)
{
middle = first + ((last - first) / 2);
compareResult = comparer(item, list[middle]);
if (compareResult > 0)
{
first = middle + 1;
if (first >= last)
{
middle++;
break;
}
continue;
}
if (compareResult < 0)
{
last = middle;
if (first == last)
{
break;
}
continue;
}
break;
}
}
if (middle == list.Count)
{
list.Add(item);
}
else
{
list.Insert(middle, item);
}
return middle;
}
答案 1 :(得分:1)
以下是一些有用的扩展方法,用于分类的IList<T>
集合(SortedBinarySearch
,SortedIndexOf
,SortedInsert
和SortedRemove
)。二进制搜索算法从ArraySortHelper<T>.InternalBinarySearch
方法的源代码中被盗。
/// <summary>Searches within the sorted <see cref="IList{T}"/> for the
/// specified item and returns the zero-based index of the item if found;
/// otherwise, a negative number that is the bitwise complement of the index of
/// the next item that is larger than item or, if there is no larger item,
/// the bitwise complement of <see cref="IList{T}.Count"/>.</summary>
public static int SortedBinarySearch<T>(this IList<T> list, T item,
IComparer<T> comparer = null)
{
if (list == null) throw new ArgumentNullException(nameof(list));
comparer = comparer ?? Comparer<T>.Default;
int lo = 0;
int hi = list.Count - 1;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
int order = comparer.Compare(list[i], item);
if (order == 0) return i;
if (order < 0)
{
lo = i + 1;
}
else
{
hi = i - 1;
}
}
return ~lo;
}
/// <summary>Searches for the specified item within the sorted
/// <see cref="IList{T}"/> and returns the zero-based index of the item
/// if found; otherwise, -1.</summary>
public static int SortedIndexOf<T>(this IList<T> list, T item,
IComparer<T> comparer = null)
{
int index = SortedBinarySearch(list, item, comparer);
if (index < 0) return -1;
return index;
}
/// <summary>Inserts an item into the sorted <see cref="IList{T}"/>.</summary>
public static int SortedInsert<T>(this IList<T> list, T item,
IComparer<T> comparer = null)
{
int index = SortedBinarySearch(list, item, comparer);
if (index < 0) index = ~index;
list.Insert(index, item);
return index;
}
/// <summary>Removes an item from the sorted <see cref="IList{T}"/> and returns
/// true if the item is successfully removed; otherwise, false.</summary>
public static bool SortedRemove<T>(this IList<T> list, T item,
IComparer<T> comparer = null)
{
int index = SortedBinarySearch(list, item, comparer);
if (index < 0) return false;
list.RemoveAt(index);
return true;
}