2015-04-15 6 views
38

Мне интересно, существует ли встроенный способ .NET для анализа битов строки.Есть ли способ лучше разбирать строки?

Возьмем, к примеру у меня есть следующая строка:

"bsarbirthd0692" 

составленную из следующих частей, которые будут перекрестные ссылки на данные позже:

Indexes Purpose 
0-3  (name) 
4-9  (description) 
10-13  (date mm-yy) 

Я надеюсь на то, как родной :

string name, desc, date; 
string.ParseFormat("{0:4}{1:5}{2:4}", "bsarbirthd0692", out name, out desc, out date); 

Есть ли собственный способ сделать это в .NET или в популярной библиотеке?

+9

довольно тривиальным реализовать себя? Его просто конвертирующая подстрока вызывает все ... –

+2

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

+0

Почему бы не JSON? или XML? – NoBugs

ответ

50

Поскольку формат известен, и не должны изменяться Substring должны работать для вас

string data = "bsarbirthd0692"; 
string name, desc, date; 
name = data.Substring(0, 4); 
desc = data.Substring(4, 6); 
date = data.SubString(10); 

EDIT

Там также методы расширения вы можете создать, чтобы делать то, что вы хотите. Это, очевидно, более сложным, чем предыдущее предложение

public static class StringExtension 
{ 
    /// <summary> 
    /// Returns a string array of the original string broken apart by the parameters 
    /// </summary> 
    /// <param name="str">The original string</param> 
    /// <param name="obj">Integer array of how long each broken piece will be</param> 
    /// <returns>A string array of the original string broken apart</returns> 
    public static string[] ParseFormat(this string str, params int[] obj) 
    { 
     int startIndex = 0; 
     string[] pieces = new string[obj.Length]; 
     for (int i = 0; i < obj.Length; i++) 
     { 
      if (startIndex + obj[i] < str.Length) 
      { 
       pieces[i] = str.Substring(startIndex, obj[i]); 
       startIndex += obj[i]; 
      } 
      else if (startIndex + obj[i] >= str.Length && startIndex < str.Length) 
      { 
       // Parse the remaining characters of the string 
       pieces[i] = str.Substring(startIndex); 
       startIndex += str.Length + startIndex; 
      } 

      // Remaining indexes, in pieces if they're are any, will be null 
     } 

     return pieces; 
    } 
} 

Использование 1:

string d = "bsarbirthd0692"; 
string[] pieces = d.ParseFormat(4,6,4); 

Результат:

enter image description here

Использование 2:

string d = "bsarbirthd0692"; 
string[] pieces = d.ParseFormat(4,6,4,1,2,3); 

Результаты :

enter image description here

+5

Упрощенный: код прост и понятен. – frenchie

+3

_ "формат известен и не должен меняться", даже если формат известен, он может измениться. Например, если данные не находятся под вашим контролем. Но перед тем, как вы его используете, просто добавьте 'Length'-check. –

+1

Решение KISS, +1 –

11

Там нет ничего подобного, однако писать что-то реализовать:

IEnumerable<string> inputString.BreakIntoLengths(4, 6, 4) 

с подписью:

public IEnumerable<string> BreakIntoLengths(this string input, params int[] lengths); 

очень легко:

public IEnumerable<string> BreakIntoLengths(this string input, params int[] lengths) { 

    var pos = 0; 
    foreach (var len in lengths) { 
    yield return input.Substring(pos, len); 
    pos += len; 
    } 
} 

(с реальной реализацией, имеющей некоторую проверку ошибок.)

NB. Я отбросил строку формата, такую ​​как интерфейс: он, похоже, не имеет значения. После возврата коллекции легко присваивать записи по индексу.

+0

Как работает работа, если я вызываю эту функцию? Немного смущен, чтобы сказать, что я никогда не видел этого ключевого слова в действии. –

+1

@SarahBourt Это делает его ленивым. Когда 'input' длинный, или имеется много длин, перечисленных, которые стремятся, генерирует много строк. Будет лениться только те, которые используются вызывающим. – Richard

2

Лучше от чего? Что-то вроде этого?

var listStrings = new List<string>(); 
var tempIndex = 0; 
var indexList = new List<int>{4, 6, 4} 
foreach(var length in indexList) 
{ 
    listStrings.Add(string.Substring(tempIndex , length); 
    tempIndex += length 
} 
2

Нет, нет встроенного способа.Я хотел бы использовать строковые методы, как Substring:

string name, desc, date; 
if (input.Length >= 4) 
{ 
    name = input.Substring(0, 4); 
    if (input.Length >= 10) 
    { 
     desc = input.Substring(4, 6); 
     if (input.Length >= 14) 
     { 
      date = input.Substring(10, 4); 
     } 
    } 
} 
16

Вы можете использовать Regexp для этого

string str= "bsarbirthd0692"; 
var regex = "(?<name>.{4})(?<desc>.{6})(?<date>.{4})"; 
MatchCollection matches = Regex.Matches(str, regex); 
foreach(Match m in matches){ 
    Console.WriteLine(m.Groups["name"].ToString()); 
    Console.WriteLine(m.Groups["desc"].ToString()); 
    Console.WriteLine(m.Groups["date"].ToString()); 
} 
+1

Регулярное выражение - это решение, о котором я сразу подумал. Почти точно соответствует желаемой семантике для OP. – mellamokb

+5

@mellamokb Регулярные выражения - отличный молот. Просто убедитесь, что вы используете их только на гвоздях: D – Luaan

+5

Регулярное выражение здесь избыточное (и OP, очевидно, представляет собой regex virgin и не нуждается в дополнительной путанице). Тем не менее, реквизит для использования названных групп, чтобы избежать полной непонятности для новичка. – dodgethesteamroller

Смежные вопросы