C# 读取数据 (CSV) 和搜索
C# Read from Data (CSV) & Search
我对从 CSV 获取数据有疑问,或者是否有推荐的其他格式?我应该使用什么数组、字典或查找?
在我的 WPF 对象中,我计划有一个搜索框和一个显示搜索结果的列表框。
数据库由两列组成,例如
Shelly, Good
Joe, Happy
Albert, Clever
Shelly, Pretty
Jessica, Lovely
Joe, Great
所以第一列是某人的名字,第二列是它的形容词。我只是举个例子来说明。基本上我会搜索第一列,一个名字可能有 "n" 个形容词,甚至只有 1 个。
我可以使用字典数据格式吗?但如果是这样的话,如果我在浏览这些行时遇到另一个值,我可以添加到键 "Shelly" 上吗?
还是使用 Lookup 更好?
CSV 文件的大小可能约为 30000 行,2 列。当我搜索 Shelly 时,我希望得到 Good, Pretty,我可以用它来填充我的列表框。
谢谢!
我会使用 Dictionnary <string, List<string>>
来存储值。
在您的情况下,名称似乎是键并且可能有多个值。
当您解析 CSV 时,您需要检查字典是否包含关键字 "Shelly" 如果不包含,则创建条目 <"Shelly, new list{"您实际得到的形容词">
如果键 "Shelly" 存在,您只需将当前形容词添加到值列表中。
可以使用;
IDictionary<string, IList<string>> myData = new Dictionary<string, IList<string>>();
Key value 包含 Shelly,List 包含 {Good, Pretty}
使用以下存储值
Dictionary<string, List<string>> databaseData = new Dictionary<string, List<string>>();
并在下方搜索使用:
List<string> results;
databaseData.TryGetValue("Shelly", out results);
将 Shelly
替换为您的搜索变量。对于上面的示例,结果将保持 Good, Pretty.
我不会为此使用嵌套的collections。你确定你会记得下周所有这些字符串的作用吗?获得形容词之一所需的双重索引怎么样,例如 dict["Lucy"][1]
?
创建一个小 class,其中包含名称和该名称的形容词,并绑定到其实例列表。从 CSV 创建列表并不比创建嵌套结构更难(实际上 更容易 )。您可以将名称用作字典的键,以便于查找。
您可以使用接受关键字和内容选择器的 GroupBy overload 将名称与形容词分开。
例如:
class Person
{
public string Name{get;set;}
public string[] Adjectives{get;set;}
}
Dictionary<string,Persons> _persons;
var lucysAdjectives = _persons["Lucy"].Adjectives;
要创建列表,您可以像创建字典一样对 CSV 值进行分组。假设您的 CSV 解析器 return 是 Item1、Item2 objects 的序列,您可以编写:
_persons = csvRows.GroupBy(
pair=>pair.Item1, //The key to group by
pair=>pair.Item2 //The group's contents
)
.ToDictionary(
g=>g.Key,
new Person{
Name=g.Key,
Adjectives=g.ToArray()
}
);
假设文件不包含 headers、引号等,您可以只读取每一行并将其拆分。在这种情况下,您可以像这样将文件读入 _persons
字典:
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.ToDictionary( g => g.Key,
new Person{ Name=g.Key, Adjectives=g.ToArray()});
您可以通过向接受名称的 Person 添加一个构造函数来简化代码,并且 IEnumerable<string>
and/or 使其不可变以防止意外修改,例如:
class Person
{
public string Name{get;}
public string[] Adjectives{get;}
Person(string Name,IEnumerable<string> adjectives)
{
Name=name;
Adjectives=adjectives.ToArray();
}
}
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.ToDictionary( g => g.Key,
new Person(g.Key, g));
或者从组中创建人 objects,然后从人中创建字典
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.Select( g => new Person(g.Key, g))
.ToDictionary( person => person.Name,
person => person);
更新
如果您不想创建小 class(为什么?)并且字典的范围很小,例如单个方法,您可以使用 C# 7 的元组。
var persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.Select( g => (Name=g.Key, Adjectives=g.ToArray()))
.ToDictionary( person => person.Name,
person => person);
范围必须很小,因为元组名称只是编译器的魔法。这些字段实际上被命名为 Item1、Item2 等。编译器魔术允许您按名称引用它们。
您也不能定义元组类型或别名,这意味着您必须在 return 类型、字段声明等中重复元组定义:
Dictionary<string,(string Name,string[] Adjectives)> _persons ;
代码很快变得丑陋
我对从 CSV 获取数据有疑问,或者是否有推荐的其他格式?我应该使用什么数组、字典或查找?
在我的 WPF 对象中,我计划有一个搜索框和一个显示搜索结果的列表框。
数据库由两列组成,例如
Shelly, Good
Joe, Happy
Albert, Clever
Shelly, Pretty
Jessica, Lovely
Joe, Great
所以第一列是某人的名字,第二列是它的形容词。我只是举个例子来说明。基本上我会搜索第一列,一个名字可能有 "n" 个形容词,甚至只有 1 个。
我可以使用字典数据格式吗?但如果是这样的话,如果我在浏览这些行时遇到另一个值,我可以添加到键 "Shelly" 上吗?
还是使用 Lookup 更好?
CSV 文件的大小可能约为 30000 行,2 列。当我搜索 Shelly 时,我希望得到 Good, Pretty,我可以用它来填充我的列表框。
谢谢!
我会使用 Dictionnary <string, List<string>>
来存储值。
在您的情况下,名称似乎是键并且可能有多个值。
当您解析 CSV 时,您需要检查字典是否包含关键字 "Shelly" 如果不包含,则创建条目 <"Shelly, new list{"您实际得到的形容词">
如果键 "Shelly" 存在,您只需将当前形容词添加到值列表中。
可以使用;
IDictionary<string, IList<string>> myData = new Dictionary<string, IList<string>>();
Key value 包含 Shelly,List 包含 {Good, Pretty}
使用以下存储值
Dictionary<string, List<string>> databaseData = new Dictionary<string, List<string>>();
并在下方搜索使用:
List<string> results;
databaseData.TryGetValue("Shelly", out results);
将 Shelly
替换为您的搜索变量。对于上面的示例,结果将保持 Good, Pretty.
我不会为此使用嵌套的collections。你确定你会记得下周所有这些字符串的作用吗?获得形容词之一所需的双重索引怎么样,例如 dict["Lucy"][1]
?
创建一个小 class,其中包含名称和该名称的形容词,并绑定到其实例列表。从 CSV 创建列表并不比创建嵌套结构更难(实际上 更容易 )。您可以将名称用作字典的键,以便于查找。
您可以使用接受关键字和内容选择器的 GroupBy overload 将名称与形容词分开。
例如:
class Person
{
public string Name{get;set;}
public string[] Adjectives{get;set;}
}
Dictionary<string,Persons> _persons;
var lucysAdjectives = _persons["Lucy"].Adjectives;
要创建列表,您可以像创建字典一样对 CSV 值进行分组。假设您的 CSV 解析器 return 是 Item1、Item2 objects 的序列,您可以编写:
_persons = csvRows.GroupBy(
pair=>pair.Item1, //The key to group by
pair=>pair.Item2 //The group's contents
)
.ToDictionary(
g=>g.Key,
new Person{
Name=g.Key,
Adjectives=g.ToArray()
}
);
假设文件不包含 headers、引号等,您可以只读取每一行并将其拆分。在这种情况下,您可以像这样将文件读入 _persons
字典:
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.ToDictionary( g => g.Key,
new Person{ Name=g.Key, Adjectives=g.ToArray()});
您可以通过向接受名称的 Person 添加一个构造函数来简化代码,并且 IEnumerable<string>
and/or 使其不可变以防止意外修改,例如:
class Person
{
public string Name{get;}
public string[] Adjectives{get;}
Person(string Name,IEnumerable<string> adjectives)
{
Name=name;
Adjectives=adjectives.ToArray();
}
}
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.ToDictionary( g => g.Key,
new Person(g.Key, g));
或者从组中创建人 objects,然后从人中创建字典
_persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.Select( g => new Person(g.Key, g))
.ToDictionary( person => person.Name,
person => person);
更新
如果您不想创建小 class(为什么?)并且字典的范围很小,例如单个方法,您可以使用 C# 7 的元组。
var persons = File.ReadLines(pathToFile)
.Select( line => line.Split(','))
.GroupBy( pair => pair[0],
pair => pair[1])
.Select( g => (Name=g.Key, Adjectives=g.ToArray()))
.ToDictionary( person => person.Name,
person => person);
范围必须很小,因为元组名称只是编译器的魔法。这些字段实际上被命名为 Item1、Item2 等。编译器魔术允许您按名称引用它们。
您也不能定义元组类型或别名,这意味着您必须在 return 类型、字段声明等中重复元组定义:
Dictionary<string,(string Name,string[] Adjectives)> _persons ;
代码很快变得丑陋