【问题标题】:c# Appropriate data structure for storing values from csv file. Specific Casec# 用于存储 csv 文件中的值的适当数据结构。具体案例
【发布时间】:2018-04-24 13:23:06
【问题描述】:

我正在编写一个程序,它将简单地读取 2 个不同的 .csv 文件,其中包含以下信息:

file 1                  file2
AA,2.34                BA,6.45
AB,1.46                BB,5.45
AC,9.69                BC,6.21
AD,3.6                 AC,7.56

第一列是string,第二列是double

到目前为止,我在阅读这些文件并将值放入列表中没有任何困难:

firstFile = new List<KeyValuePair<string, double>>();
secondFile = new List<KeyValuePair<string, double>>();

我正在尝试指导我的程序:

  • 从第一个文件的第一行的第一列中获取第一个值(在本例中为AA
  • 并查看第二个文件的整个第一列中是否存在匹配项。
  • 如果找到字符串匹配,比较它们对应的第二个值(在这种情况下为double),如果在这种情况下找到匹配,则将整行添加到单独的List

类似于下面的伪代码

for(var i=0;i<firstFile.Count;i++)
{
    firstFile.Column[0].value[i].SearchMatchesInAnotherFile(secondFile.Column[0].values.All);
    if(MatchFound)
    {
        CompareCorrespondingDoubles();
        if(true)
        {
            AddFirstValueToList();
        }
    }
}

我尝试使用Dictionary 而不是List,但是这个数据结构没有排序并且无法通过索引访问键。

不是要求提供确切的代码,而是问题是:

您建议使用什么作为该程序的合适数据结构,以便我可以进一步调查自己?

【问题讨论】:

  • 字典应该完全符合您的要求。 myDictionary[key] 返回分配给给定键的值。要快速转换现有列表,您可以使用此 linq:stackoverflow.com/a/4022334/361842
  • 一个键可以在同一个文件中重复吗?还是独一无二的?
  • 没有。字典中不允许有重复的键
  • @MongZhu 不,密钥不会在我的程序的同一个文件中重复。这就是逻辑。
  • @Butler1233:我认为MongZhu 是在询问TiredOfProgramming 的要求;即查看字典是否适合此用例。

标签: c# csv data-structures


【解决方案1】:

KeyValuePair实际上只用于Dictionarys。我建议创建自己的自定义类型:

public class MyRow
{
    public string StringValue {get;set;}
    public double DoubleValue {get;set;}

    public override bool Equals(object o)
    {
         MyRow r = o as MyRow;
         if (ReferenceEquals(r, null)) return false;
         return r.StringValue == this.StringValue && r.DoubleValue == this.DoubleValue;
    }
    public override int GetHashCode()
    {
        unchecked { return StringValue.GetHashCode ^ r.DoubleValue.GetHashCode(); }
    }
}

并将文件存储在这种类型的列表中:

List<MyRow> firstFile = ...
List<MyRow> secondFile = ...

然后您可以通过 LINQ 的 Intersect 方法确定 交集(两个列表中出现的所有元素):

var result = firstFile.Intersect(secondFile).ToList();

必须覆盖EqualsGetHashCode,否则Intersect 只会进行引用比较。或者,您可以实现自己的 IEqualityComparer&lt;MyRow, MyRow&gt; 进行比较并将其传递给适当的 Intersect 重载。


但是如果你能保证keys(字符串值是唯一的),你也可以使用一个

Dictionary<string, double> firstFile = ...    
Dictionary<string, double> secondFile = ...

在这种情况下使用这个 LINQ 语句:

var result = new Dictionary<string, double>(
          firstFile.Select(x => new { First = x, Second = secondFile.FirstOrDefault(y => x.Key == y.Key) })
                   .Where(x => x.Second?.Value == x.First.Value));

它的时间复杂度为 O(m+n),而上层解为 O(m*n)(因为 m 和 n 是两个文件的行数)。

【讨论】:

  • 我正在考虑这个解决方案,但不想在我的程序中变得那么复杂。让我在代码中尝试一下,稍后我会回复结果。感谢您的帮助。
  • @TiredOfProgramming 您可以使用Tuple&lt;string, double&gt; 代替已经内置EqualsGetHashCodeMyRow
  • @Spotted 是的,考虑了一下.. 但是,我喜欢特定的自定义类型,因为您经常想添加更多属性或方法。但在这种特殊情况下,Tuple&lt;string,double&gt; 就足够了。
  • 我们在这里谈论的是 firstFile = new List>();
  • @TiredOfProgramming 是
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
  • 2017-01-24
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多