c # Соответствующая структура данных для хранения значений из CSV-файла. Особый случай - PullRequest
0 голосов
/ 24 апреля 2018

Я пишу программу, которая будет просто читать 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();
        }
    }
}

Вместо List Я пытался использовать Dictionary, но эта структура данных не сортируется и нет способа получить доступ к ключу по индексу.

Я не запрашиваю точный код для предоставления , скорее вопрос:

Что бы вы предложили использовать в качестве подходящей структуры данных для этой программы, чтобы я мог исследовать себя дальше?

1 Ответ

0 голосов
/ 24 апреля 2018

KeyValuePair фактически используется только для Dictionary с.Я предлагаю создать свой собственный тип:

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

Необходимо переопределить Equals и GetHashCode, потому что в противном случае Intersect сделает только ссылка сравнение.В качестве альтернативы вы можете реализовать собственный IEqualityComparer<MyRow, MyRow>, который выполняет сравнение и передать его соответствующей перегрузке Intersect.


Но если вы можете убедиться, что ключи (строковые значения являются уникальными), вы также можете использовать

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 - количество строк в двух файлах).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...