C#从数据读取(CSV)&搜索

时间:2017-09-13 09:27:55

标签: c# wpf csv dictionary lookup

我对从CSV获取数据有疑问,还是建议使用其他格式?我应该使用什么数组或字典或查找?

在我的WPF对象中,我打算有一个搜索框和一个显示搜索结果的列表框。

数据库由两列组成,例如

  雪莉,好郎   乔,快乐
  艾伯特,聪明的   雪莉,漂亮的   杰西卡,可爱的   乔,伟大

所以第一列是某人的名字,第二列是它的形容词。我只是举一个例子来说明。基本上我会搜索第一列,并且单个名称可能有" n"形容词的数量甚至只是1。

我可以使用字典数据格式吗?但如果是这样的话,我可以加入关键词" Shelly"如果在通过这些线路时遇到另一个值?

或者使用Lookup更好吗?

CSV文件的大小可能约为30000行,2列。当我搜索Shelly时,我希望得到Good,Pretty,我可以使用它来填充我的列表框。

谢谢!

4 个答案:

答案 0 :(得分:0)

我会使用Dictionnary <string, List<string>>来存储值。

在您的情况下,名称似乎是关键,可能有多个值。

当您解析CSV时,您需要检查字典是否包含Key“Shelly”,否则您创建条目&lt;“Shelly,新列表{”您实际得到的形容词“&gt;

如果存在“Shelly”键,则只需将当前形容词添加到值列表中。

答案 1 :(得分:0)

你可以使用;

IDictionary<string, IList<string>> myData = new Dictionary<string, IList<string>>();

键值保持Shelly,List将保持{Good,Pretty}

答案 2 :(得分:0)

使用以下内容存储值

Dictionary<string, List<string>> databaseData = new  Dictionary<string, List<string>>();

并在下面搜索使用:

List<string> results; 
databaseData.TryGetValue("Shelly", out results);

Shelly替换为您的搜索变量。对于上面的例子,结果将保持良好,漂亮。

答案 3 :(得分:0)

不会使用嵌套集合。你确定你会记得下周所有这些字符串的作用吗?如何获得其中一个形容词所需的doule索引,例如dict["Lucy"][1]

创建一个包含该名称的名称和形容词的小类,并绑定到其实例列表。与创建嵌套结构相比,从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解析器返回Item1,Item2对象的序列,您可以写:

_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()
                            }
                      );

假设文件不包含标题,引号等,您可以只读取每一行并将其拆分。在这种情况下,您可以将文件读入_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()});

您可以通过向接受名称和IEnumerable<string>的Person添加构造函数来简化代码,和/或使其不可变以防止意外修改,例如:

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));

或从组中创建Person对象,然后从Persons

创建一个字典
_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);

<强>更新

如果你不想创建小类(为什么?)并且字典的范围很小,例如单个方法,你可以使用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等。编译器魔术允许您按名称引用它们。

您也无法定义元组类型或别名,这意味着您必须在返回类型,字段声明等中重复元组定义:

Dictionary<string,(string Name,string[] Adjectives)> _persons ;

代码变得非常丑陋