Как разделить строку C #, если член массива может состоять из более чем одного слова? - PullRequest
0 голосов
/ 12 ноября 2008

Я работаю над небольшим проектом, чтобы взять файл CSV и затем вставить его данные в таблицу HTML (я хотел бы использовать datagrid и набор данных или datatable, но система, с которой я буду говорить, не поддерживает загрузки ASP.NET для рассылка новостей).

В любом случае, я буду использовать метод file.readalllines для возврата содержимого файла csv в строковый массив.

Но для каждого строкового члена массива я буду использовать функцию string.split, чтобы разбить строку на массив char. Проблема в том (и файл csv создается системой, с которой я разговариваю, кстати - я получаю данные из этой системы и передаю данные в нее), содержимое csv - это автомобили. Это означает, что я мог бы иметь:

Ниссан Альмера

Nissan Almera 1.4 TDi

VW Golf 1.9 SE

И так далее ...

Есть ли надежный способ, которым я мог бы гарантировать, что там, где у меня есть Almera 1.4 TDi, например, это один элемент в массиве символов, на который я разбил каждую строку, а не отдельные элементы.

Ответы [ 6 ]

3 голосов
/ 12 ноября 2008

Используйте перегруженную версию string.Split(), которая ограничивает количество возвращаемых значений.

    string makeModel = csvArray[0]; // or whichever column it is in
    string[] makeAndModel = makeModel.Split( new char[] { ' ' } , 2 );
    string make = makeAndModel[0];
    string model = makeAndModel[1];
0 голосов
/ 14 ноября 2008

Как заметил кто-то другой, string.split () принимает параметр, так что вы можете передать ',' для разделения на основе этого. Не имеет значения, если у вас есть пробелы в значениях. Если вы действительно не уверены, что у вас не будет значений, содержащих запятые, я не рекомендую делать это. Парсинг CSV-файлов немного сложнее, чем может показаться вначале (обработка кавычек и значений, содержащих запятые), и я предлагаю использовать для этого существующую библиотеку, например http://www.codeproject.com/KB/database/CsvReader.aspx.

0 голосов
/ 12 ноября 2008

Как я понимаю вопрос:

  • Строки в анализируемом файле НЕ являются CSV, они разделены пробелом.
  • Значение первого поля каждой строки (марка / модель) может содержать 0 или более фактических пробелов.
  • Значения других полей в каждой строке не содержат пробелов, поэтому для них отлично работает разделитель пробелов.

Допустим, у вас есть четыре столбца, и значением первого столбца считается «Nissan Almera 1.4 TDi». Использование обычного метода Split () приведет к получению 7 полей, а не 4.

(непроверенный код)

Сначала просто разбейте его:

int numFields = 4;
string[] myFields = myLine.Split(' ');

Затем исправьте массив:

int extraSpaces = myFields.length-numFields;
if(extraSpaces>0) {
  // Piece together element 0 in the array by adding the extra elements
  for(int n = 1; n <= extraSpaces; n++) {
    myFields[0] += ' ' + myFields[n];
  }
  // Move the other values back to elements 1, 2, and 3 of the array
  for(int n = 1; n < numFields; n++) {
    myFields[n] = myFields[n + extraSpaces];
    }
  }

Наконец, игнорируйте каждый элемент массива, кроме четырех, которые вы на самом деле хотели разобрать.

Другим подходом были бы регулярные выражения. Я думаю, что-то вроде этого будет работать:

 MatchCollection m = RegEx.Matches(myLine, "^(.*) ([^ ]+) ([^ ]+) ([^ ]+)$");
 string MakeModel = m.Groups[1].Captures[0].ToString();
 string ModelYear = m.Groups[2].Captures[0].ToString();     
 string Price     = m.Groups[3].Captures[0].ToString();     
 string NumWheels = m.Groups[4].Captures[0].ToString();

Здесь нет разбиений или массивов, только захваченные RegEx группы.

Если был встроенный метод String.Reverse () (его нет), я мог бы предложить использовать функцию Replace () VB.NET с параметром Count для замены всех пробелов после первых трех пробелов (при условии четырех полей) в перевернутой необработанной строке, затем перевернуть ее снова и разделить. Что-то вроде:

string[] myFields = Microsoft.VisualBasic.Replace(myLine.Reverse(), " ", "_", 0, 3).Reverse().Split(' ');
myFields[0] = myFields[0].Replace("_", " "); //fix the underscores
0 голосов
/ 12 ноября 2008

Вам нужно будет использовать регулярное выражение.

Я не уверен, что вам нужно регулярное выражение, но вы могли бы решить проблему с одним, и тогда у вас будет 2 проблемы.

5-секундный поиск Google regex csv дает запись в блоге

,(?=([^"]*"[^"]*")*(?![^"]*"))

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

Имейте в виду, что это неудачно, если у вас есть входная строка, такая как

123,456,"Unbalanced quote

Где это не соответствует ни одной запятой.


Шаг 2, Другой поиск Google, на этот раз для c# split csv files

CSV ФАЙЛЕР И ПИСАТЕЛЬ ФАЙЛОВ В C # (ЧАСТЬ 3) (но проверьте код в частях 1 и 2)

Выглядит намного надежнее и даже имеет тестовые случаи.

Поскольку не существует стандартного формата CSV, вам нужно будет судить, работает ли это для входных файлов, которые вы разрешаете.

0 голосов
/ 12 ноября 2008

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

EG: Nissan Almera Nissan _X100_Ultra_Model Префект Форд Тойота Фу Бар Хонда Приус

Разбор по основным брендам (Nissan, Ford, Toyota, Honda) даст:

  • Ниссан Альмера
  • Nissan _X100_Ultra_Model
  • Префект Форд
  • Toyota Foo Bar
  • Honda Prius
0 голосов
/ 12 ноября 2008

Метод Split () принимает параметр char, который можно использовать для указания разделителя. Таким образом, вы можете сделать что-то вроде:

String.Split(Convert.ToChar(","));

Судя по вашему вопросу, все марки автомобилей должны быть разделены запятыми, чтобы это работало.

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