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