C # — LinQ — читать текстовые файлы, группировать по первому столбцу и упорядочивать по последнему столбцу?

#c# #linq

#c# #linq

Вопрос:

у привет есть текстовые файлы, которые содержат 3 столбца, что-то вроде этого:

 contract1;pdf1;63
contract1;pdf2;5
contract1;pdf3;2
contract1;pdf4;00
contract2;pdf1;2
contract2;pdf2;30
contract2;pdf3;5
contract2;pdf4;80
  

теперь я хочу записать эту информацию в другие текстовые файлы, и на выходе будет порядок, установленный для первых записей с последним столбцом в «2,5», что-то вроде этого:

 contract1;pdf3;2
contract1;pdf2;5
contract1;pdf1;63
contract1;pdf4;00
contract2;pdf1;2
contract2;pdf3;5
contract2;pdf2;30
contract2;pdf4;80
  

как я могу сделать?
Спасибо

Комментарии:

1. Я бы начал с чтения joshclose.github.io/CsvHelper/getting-started . Затем learn.microsoft.com/en-us/dotnet/api /… и learn.microsoft.com/en-us/dotnet/api /.

2. Хм. Ваши данные отличаются. В первом примере у вас есть строка contract1;pdf1;63 , а contract1;pdf3;2 во втором у вас есть contract1;pdf1;2 , и contract1;pdf3;63 поэтому pdf1 и pdf3 поменяли их значение. Почему?

3. Такой метод должен помочь вам начать: File.ReadAllLines("Path to file").Select(line => line.Split(";")); — это вернет вам массив массивов, где каждый элемент представляет одну ячейку из файла CSV.

4. Пожалуйста, перепишите предложение, начинающееся с «теперь я хочу написать», чтобы было понятнее.

Ответ №1:

Вы можете использовать LINQ для группировки и сортировки строк после чтения, а затем собрать их вместе:

 var output = File.ReadAllLines(@"path-to-file")
                 .Select(s => s.Split(';'))
                 .GroupBy(s => s[0])
                 .SelectMany(sg => sg.OrderBy(s => s[2] == "2" ? "-" : s[2] == "5" ? " " : s[2]).Select(sg => String.Join(";", sg)));
  

Затем просто запишите их в файл.

Комментарии:

1. это идеально подходит для меня!! спасибо, ты лучший программист! большое спасибо

Ответ №2:

Я не собираюсь писать вашу программу за вас, но я бы порекомендовал эту библиотеку для чтения и записи файлов с разделителями: https://joshclose.github.io/CsvHelper/getting-started /

При запуске программы чтения обязательно укажите разделитель с запятой:

 using (var reader = new StreamReader("path\to\input_file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    csv.Configuration.Delimiter = ";";
    var records = csv.GetRecords<Row>();
    // manipulate the data as needed here
}
  

Ваш класс «Row» (выберите более подходящее имя для ясности) укажет схему плоского файла. Похоже, у вас нет заголовков? Если нет, вы можете указать порядок каждого элемента.

 public class Row
{
    [Index(1)]
    public string MyValue1 { get; set; }
    [Index(2)]
    public string MyValue2 { get; set; }
}
  

После считывания данных вы можете манипулировать ими по мере необходимости. Если формат вывода отличается от формата ввода, вы должны преобразовать входной класс в выходной класс. Вы можете использовать библиотеку Automapper, если хотите. Однако для простого проекта я бы предложил просто вручную преобразовать входной класс в выходной класс.

Наконец, запишите данные обратно:

 using (var writer = new StreamWriter("path\to\output_file.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{    
    csv.WriteRecords(records);
}