我有按特定顺序填充的List集合(要求是,此顺序无法更改)。此列表包含实体类型对象。
在列表的初始填充之后,我需要插入更多来自另一个数据源的对象。这些对象需要插入特定位置,以便排序正确。
例如,如果初始列表具有以下元素
在初始填充后我想插入“ABB”元素,需要在3和4之间插入。
目前,我有以下方法为新元素找到正确的位置。
private static int FindPositionForArticle(string word)
{
string key = word.ToLower();
for (int i = word.Length; i >= 0; i--)
{
if(i < word.Length)
key = key.Remove(i, 1);
int pos = 0;
int insertPos = 0;
foreach(ArticleEntity article in list)
{
if(article.Text.ToLower().StartsWith(key))
insertPos = pos;
else if (!article.Text.ToLower().StartsWith(key) && insertPos > 0)
return insertPos++;
pos++;
}
}
return 0;
}
这种方法背后的目的是:
选择需要插入的“单词”并尝试查找与“单词”同名的元素的位置
如果未找到任何内容,请从“字词”中删除最后一个字符,然后重新搜索。
重复删除最后一个字符,直到找到最佳位置。
不幸的是我的方法有bug(实现不正确)。目前我的方法表明最佳位置为0,这是完全错误的。
如果您想使用我的示例代码,可以在以下位置下载:
http://dl.getdropbox.com/u/204110/FindPosition.cs.txt
提前谢谢你。
答案 0 :(得分:5)
int index = list.BinarySearch(word);
如果index为正数或零,则在列表中找到该项目。如果为负数,则它包含列表中下一个最高项的索引的按位补码。
所以,为此:
List<string> list = new List<string>{"AAA","AAB","AAC","ACC","ADA"};
int index = list.BinarySearch("ABB"); // => -4
int insertIndex = ~index; // => 3
list.Insert(insertIndex, "ABB");
答案 1 :(得分:2)
类型字符串的SortedList不会更好吗?
答案 2 :(得分:2)
由于您可以通过索引访问该列表,因此您可能希望实现类似于Chris Doggett的anwser的二进制搜索。这将为您提供比当前按顺序实现它更好的运行时间:
您的运行时当前与列表中的项目数呈线性关系,如果您插入 n 这样的项目,您将获得大约 n 2 操作。
使用二进制搜索(顺便说一句,内部为SortedList
),每个插入的 log2(n)的运行时间会更好,例如: * n *** log2(n)*插入n个项目时的总运行时间。
二元搜索的基本思想很简单:
列出项目
首先,您将整个范围视为可能的位置(左= 0,右=列表中的当前计数)
如果左边等于右边,你找到了合适的位置
否则,选择中间元素(左+右)/ 2并将其与要插入的键进行比较。
答案 3 :(得分:1)
您是否考虑过使用SortedList数据结构?如果它将包含需要以特定方式排序的复杂数据类型,则可以创建指定IComparer对象的数据类型。
IComparer唯一要做的就是能够确定一个项目之前或之后是否属于一个项目。鉴于此,SortedList将正确保持顺序。
使用此结构可以保证在内部指定时保持顺序,这样您就不必维护基本上实现排序的代码。
答案 4 :(得分:1)
此代码:
private static System.Collections.SortedList list = new System.Collections.SortedList();
static void Main(string[] args)
{
list.Add("AAA" , "AAA");
list.Add("AAB", "AAB");
list.Add("AAC", "AAC");
list.Add("ACC", "ACC");
list.Add("ADA", "ADA");
Console.WriteLine("List before");
for (int j = 0; j < list.Count ; j++)
{
Console.WriteLine(list.GetByIndex(j));
}
list.Add("ABB","ABB");
Console.WriteLine(list.IndexOfKey("ABB"));
for (int j = 0; j < list.Count; j++)
{
Console.WriteLine(list.GetByIndex(j));
}
Console.ReadLine();
}
正在您需要的位置插入项目..
或者你还需要别的吗?没有比较Icompare,你正在排序常见的字符串。
答案 5 :(得分:1)
我已经完成了你想要做的事情。您有一个ArticleEntity对象列表。您需要对此列表进行排序。首先,您需要添加对您的类进行排序的功能。我的例子是在VB中,不应该太难转换为C#。
为您的班级添加排序,如下所示:
Public Class ArticleEntity
Implements IComparable(Of ArticleEntity)
Public Overloads Function CompareTo(ByVal Other As ArticleEntity) As Integer _
Implements IComparable(Of ArticleEntity).CompareTo
Return Me._PropertyToSort.CompareTo(Other._PropertyToSort)
End Function
然后,在添加了需要添加到List Of(ArticleEntity)的所有内容之后,您可以:
MyListOfArticleEntities.Sort()
我认为这就是你要找的东西。如果不是,请告诉我。
答案 6 :(得分:1)
您的收藏是否需要是List
?
如果在插入新元素之前不需要从列表中访问元素,heap听起来会更好地完成工作。基本上你会:
List
。每个步骤中的每个步骤仅为每个对象的O(log n)时间。我确信C#实现了堆。
注意:我的意思是“堆”在数据结构的意义上,而不是全局内存池。