May*_*kar 82 .net c# linq collections sortedlist
我正在编写一个程序来设置一个序列,其中各种对象将出现在报告中.序列是Excel电子表格中的Y位置(单元格).
代码的演示部分如下.我想要完成的是拥有一个集合,这将允许我添加多个对象,我可以根据序列获得一个排序的集合
SortedList list = new SortedList();
Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);
h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);
Run Code Online (Sandbox Code Playgroud)
我知道SortedList不允许这样,我一直在寻找替代品.我不想消除重复,已经尝试过了List<KeyValuePair<int, object>>.
谢谢.
Kna*_*bax 67
使用您自己的IComparer!
就像在其他一些答案中已经说过的那样,你应该使用你自己的比较器类.为此,我使用了一个通用的IComparer类,它可以与任何实现IComparable的东西一起使用:
/// <summary>
/// Comparer for comparing two keys, handling equality as beeing greater
/// Use this Comparer e.g. with SortedLists or SortedDictionaries, that don't allow duplicate keys
/// </summary>
/// <typeparam name="TKey"></typeparam>
public class DuplicateKeyComparer<TKey>
:
IComparer<TKey> where TKey : IComparable
{
#region IComparer<TKey> Members
public int Compare(TKey x, TKey y)
{
int result = x.CompareTo(y);
if (result == 0)
return 1; // Handle equality as beeing greater
else
return result;
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
在实例化新的SortedList,SortedDictionary等时,您将使用它:
SortedList<int, MyValueClass> slist = new SortedList<int, MyValueClass>(new DuplicateKeyComparer<int>());
Run Code Online (Sandbox Code Playgroud)
这里int是可以重复的键.
小智 13
您可以安全地使用List <>.List有一个Sort方法,其重载接受IComparer.您可以创建自己的分拣机类.这是一个例子:
private List<Curve> Curves;
this.Curves.Sort(new CurveSorter());
public class CurveSorter : IComparer<Curve>
{
public int Compare(Curve c1, Curve c2)
{
return c2.CreationTime.CompareTo(c1.CreationTime);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 9
我使用以下内容:
public class TupleList<T1, T2> : List<Tuple<T1, T2>> where T1 : IComparable
{
public void Add(T1 item, T2 item2)
{
Add(new Tuple<T1, T2>(item, item2));
}
public new void Sort()
{
Comparison<Tuple<T1, T2>> c = (a, b) => a.Item1.CompareTo(b.Item1);
base.Sort(c);
}
}
Run Code Online (Sandbox Code Playgroud)
我的测试用例:
[TestMethod()]
public void SortTest()
{
TupleList<int, string> list = new TupleList<int, string>();
list.Add(1, "cat");
list.Add(1, "car");
list.Add(2, "dog");
list.Add(2, "door");
list.Add(3, "elephant");
list.Add(1, "coconut");
list.Add(1, "cab");
list.Sort();
foreach(Tuple<int, string> tuple in list)
{
Console.WriteLine(string.Format("{0}:{1}", tuple.Item1,tuple.Item2));
}
int expected_first = 1;
int expected_last = 3;
int first = list.First().Item1; //requires using System.Linq
int last = list.Last().Item1; //requires using System.Linq
Assert.AreEqual(expected_first, first);
Assert.AreEqual(expected_last, last);
}
Run Code Online (Sandbox Code Playgroud)
输出:
1:cab
1:coconut
1:car
1:cat
2:door
2:dog
3:elephant
Run Code Online (Sandbox Code Playgroud)
问题是数据结构设计不符合要求:需要为同一个XPos存储多个Headers。因此,SortedList<XPos, value>不应具有 的值Header,而是具有 的值List<Header>。这是一个简单而小的更改,但它解决了所有问题并避免了像其他建议的解决方案一样产生新问题(请参阅下面的解释):
using System;
using System.Collections.Generic;
namespace TrySortedList {
class Program {
class Header {
public int XPos;
public string Name;
}
static void Main(string[] args) {
SortedList<int, List<Header>> sortedHeaders = new SortedList<int,List<Header>>();
add(sortedHeaders, 1, "Header_1");
add(sortedHeaders, 1, "Header_2");
add(sortedHeaders, 2, "Header_3");
foreach (var headersKvp in sortedHeaders) {
foreach (Header header in headersKvp.Value) {
Console.WriteLine(header.XPos + ": " + header.Name);
}
}
}
private static void add(SortedList<int, List<Header>> sortedHeaders, int xPos, string name) {
List<Header> headers;
if (!sortedHeaders.TryGetValue(xPos, out headers)){
headers = new List<Header>();
sortedHeaders[xPos] = headers;
}
headers.Add(new Header { XPos = xPos, Name = name });
}
}
}
Output:
1: Header_1
1: Header_2
2: Header_3
Run Code Online (Sandbox Code Playgroud)
请注意,添加“有趣”的键,例如添加随机数或假装具有相同值的 2 个 XPos 不同会导致许多其他问题。例如,删除特定的标题变得困难甚至不可能。
另请注意,如果只List<Header>需要排序少数比每个Header. 示例:如果有 100 个 XPos 并且每个都有 100 个标题,则 10000Header需要排序而不是 100 List<Header>。
当然,这个方案也有一个缺点:如果有很多只有 1 个 Header 的 XPos,那么需要创建很多 List,这是一些开销。
最简单的解决方案(与上述所有相比):use SortedSet<T>,它接受一个IComparer<SortableKey>类,然后以这种方式实现Compare方法:
public int Compare(SomeClass x, SomeClass y)
{
var compared = x.SomeSortableKeyTypeField.CompareTo(y.SomeSortableKeyTypeField);
if (compared != 0)
return compared;
// to allow duplicates
var hashCodeCompare = x.GetHashCode().CompareTo(y.GetHashCode());
if (hashCodeCompare != 0)
return hashCodeCompare;
if (Object.ReferenceEquals(x, y))
return 0;
// for weird duplicate hashcode cases, throw as below or implement your last chance comparer
throw new ComparisonFailureException();
}
Run Code Online (Sandbox Code Playgroud)
非常感谢你的帮助。在进行更多搜索时,我找到了这个解决方案。(可在 Stackoverflow.com 的其他问题中找到)
首先,我创建了一个类,它将封装我的类对象(页眉、页脚等)
public class MyPosition
{
public int Position { get; set; }
public object MyObjects{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
所以这个类应该保存对象,并且每个对象的 PosX 都是 int Position
List<MyPosition> Sequence= new List<MyPosition>();
Sequence.Add(new MyPosition() { Position = 1, Headerobject });
Sequence.Add(new MyPosition() { Position = 2, Headerobject1 });
Sequence.Add(new MyPosition() { Position = 1, Footer });
League.Sort((PosA, PosB) => PosA.Position.CompareTo(PosB.Position));
Run Code Online (Sandbox Code Playgroud)
最终我得到的是排序后的“序列”列表。
| 归档时间: |
|
| 查看次数: |
63807 次 |
| 最近记录: |