C#:对键为 List<object> 的字典进行排序
Posted
技术标签:
【中文标题】C#:对键为 List<object> 的字典进行排序【英文标题】:C#: Sorting a dictionary in which the keys are List<object> 【发布时间】:2021-02-12 20:19:49 【问题描述】:大家好! Tl;博士我有一个Dictionary<string, List<object>>
叫
具有以下键的“表”:
"id" being int,
"date" being Datetime,
"name", "entry1", "entry2", "entry3" being strings.
以及List<object>
列表中键的所有值。我想通过name
字段订购字典,名称类似于“John Doe”。我尝试使用 .OrderBy() ,它要么抛出异常,要么只订购那个键而不是整个字典。例如:var result = table.Orderby(pairs => pairs.Value[2]);
会抛出异常,因为对象不是字符串。
如何才能做到这一点?谢谢!
编辑: 该表用于使用 Excel 文件中的值:
foreach (var key in table.Keys)
for (int i = 0; i < max; i++)
switch (key)
case "id":
worksheet.Cells[i + 1, j].Value = ConversionWrapper<int>((int)table[key][i]);
break;
case "date":
worksheet.Cells[i + 1, j].Value = ConversionWrapper<string>((DateTime)table[key][i]);
break;
case "name":
case "entry1":
case "entry2":
case "entry3":
case "entry4":
worksheet.Cells[i + 1, j].Value = ConversionWrapper<string>((string)table[key][i]);
break;
default:
break;
++j;
private static T ConversionWrapper<T>(object elem)
switch (elem)
case int:
case string:
return (T)elem;
case DateTime:
return (T)(object)((DateTime)elem).ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
default:
throw new ArgumentException();
Method to extract the values:
private static Dictionary<string, List<object>> GetAllElementsLM(SqlConnection conn)
string query;
string[] columns = "id", "date", "name", "entry1", "entry2", "entry3", "entry4" ;
var dic = new Dictionary<string, List<object>>();
conn.Open();
foreach (var elem in columns)
dic.Add(elem, new List<object>());
query = $@"SELECT elem FROM ""feedback""";
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
dic[elem].Add(reader.GetValue(0));
conn.Close();
return dic;
【问题讨论】:
"我有一个名为 "table" 的Dictionary<string, List<object>>
带有以下键" 考虑到 int
和 DateTime
不是从 string
派生的,这是不可能的。
@JohnathanBarclay 键是字符串,我指的是我将对象值转换为
您不需要对字典进行排序。如果你这样做了,那么 Dictionary 不是要使用的正确数据结构。字典专为键/值查找而设计
您想要一本有序的字典吗?或者您是否尝试将字典投影到 new 有序数据结构中?
@mjwills 我不“想要”字典。这些值是从 SQL 表中提取的,我发现字典似乎很合适。我希望所有 7 个条目(id、日期、名称等)都被“链接”,无论我需要使用什么数据类型。
【参考方案1】:
您要排序的类(本例中为列表)需要实现 IComparer 接口。然后 OrderBy 运算符调用 IComparer.Compare 来确定排序顺序。
IComparer.Compare
所以你需要创建一个扩展 List 并实现 IComparer 的类。在此类的比较方法中,您可以执行任何必要的操作来确定哪个列表更大(例如,基于列表中的某个值)。然后,您的字典会将这个新类作为第二种类型。
【讨论】:
【参考方案2】:最终使用了我的结构的List
:
条目结构:
readonly struct Entries
public int Id get;
public DateTime Date get;
public string Name get;
public string Entry1 get;
public string Entry2 get;
public string Entry3 get;
public string Entry4 get;
public Entries(int id, DateTime date, string name, string entry1, string entry2, string entry3, string entry4) =>
(Id, Date, Name, Entry1, Entry2, Entry3, Entry4) = (id, date, name, entry1, entry2, entry3, entry4);
获取元素个数的方法:
private static int GetMaxNumber(SqlConnection conn)
int i = 0;
string query;
conn.Open();
query = $@"SELECT id FROM ""feedback""";
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
++i;
conn.Close();
return i;
获取元素:
private static IEnumerable<Entries> GetAllElementsClass(SqlConnection conn)
string query;
List<int> id;
List<DateTime> date;
List<string> name, entry1, entry2, entry3, entry4;
int max = GetMaxNumber(conn);
conn.Open();
query = $@"SELECT id FROM ""feedback""";
id = new List<int>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
id.Add((int)reader.GetValue(0));
query = $@"SELECT date FROM ""feedback""";
date = new List<DateTime>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
date.Add((DateTime)reader.GetValue(0));
query = $@"SELECT name FROM ""feedback""";
name = new List<string>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
name.Add((string)reader.GetValue(0));
query = $@"SELECT entry1 FROM ""feedback""";
entry1 = new List<string>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
entry1.Add((string)reader.GetValue(0));
query = $@"SELECT entry2 FROM ""feedback""";
entry2 = new List<string>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
entry2.Add((string)reader.GetValue(0));
query = $@"SELECT entry3 FROM ""feedback""";
entry3 = new List<string>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
entry3.Add((string)reader.GetValue(0));
query = $@"SELECT entry4 FROM ""feedback""";
entry4 = new List<string>();
using (var command = new SqlCommand(query, conn))
using (var reader = command.ExecuteReader())
while (reader.Read())
entry4.Add((string)reader.GetValue(0));
for (int i = 0; i < max; i++)
yield return new Entries(id[i], date[i], name[i], entry1[i], entry2[i], entry3[i], entry4[i]);
conn.Close();
对它们进行排序:
private static List<Entries> SortEntries(SqlConnection conn)
var entries = new List<Entries>();
foreach (var element in GetAllElementsClass(conn))
entries.Add(element);
entries = entries.OrderBy(x => x.Name).ToList();
return entries;
【讨论】:
以上是关于C#:对键为 List<object> 的字典进行排序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中将 List<object> 转换为 Hashtable?
C# 在运行时将 Enumerable.Iterator 强制转换为已知 List<Object>