2011-12-13 138 views
0

我有一個包含下列值的數組:字符串分割到

str[0]= "MeterNr 29202" 
str[1]="- 20111101: position 61699 (Previous calculation) " 
str[2]="- 20111201: position 68590 (Calculation) consumption 6891 kWh" 
str[3]="- 20111101: position 75019 (Previous calculation) " 
str[4]="MeterNr 50273" 
str[5]="- 20111101: position 18103 (Previous reading) " 
str[6]="- 20111201: position 19072 (Calculation) consumption 969 kWh " 

我想在邏輯順序行分割,這樣我可以將它們存儲在下面的閱讀課。我在分割值時遇到問題。括號()中的所有內容都是ItemDescription。

我會感謝您的快速回答。

public class Reading 
{ 
    public string MeterNr { get; set; } 

    public string ItemDescription { get; set; } 

    public string Date { get; set; } 

    public string Position { get; set; } 

    public string Consumption { get; set; } 
} 
+0

你能否更具體?輸出應該如何?換句話說,應該返回MeterNr,ItemDescription等。 – Perlnika

+0

有幾種選擇。一個是檢查(IndexOf)的開始(和結束),並採取內部。或者你可以用正則表達式來做到這一點。 – lnu

+0

嘗試使用英語(或您選擇的語言)來描述您想要的每一行內容,那應該給您提示您應該做什麼。進一步的提示:它似乎並不需要*正則表達式,一個簡單的IndexOf/substring已經可以提供幫助。 –

回答

2

我只是使用一個for循環和字符串索引等,但後來我有點簡單!不知道你的數據(即,如果事情可能會丟失),但是這會在您發佈的數據工作...

var readings = new List<Reading>(); 
int meterNrLength = "MeterNr".Length; 
int positionLength = "position".Length; 
int consumptionLength = "consumption".Length; 
string meterNr = null; 

foreach(var s in str) 
{ 
    int meterNrIndex = s.IndexOf("MeterNr", 
           StringComparison.OrdinalIgnoreCase); 

    if (meterNrIndex != -1) 
    { 
     meterNr = s.Substring(meterNrIndex + meterNrLength).Trim(); 
     continue; 
    } 

    var reading = new Reading {MeterNr = meterNr}; 

    string rest = s.Substring(0, s.IndexOf(':')); 
    reading.Date = rest.Substring(1).Trim(); 

    rest = s.Substring(s.IndexOf("position") + positionLength); 

    int bracketIndex = rest.IndexOf('('); 

    reading.Position = rest.Substring(0, bracketIndex).Trim(); 

    rest = rest.Substring(bracketIndex + 1); 

    reading.ItemDescription = rest.Substring(0, rest.IndexOf(")")); 

    int consumptionIndex = rest.IndexOf("consumption", 
             StringComparison.OrdinalIgnoreCase); 

    if (consumptionIndex != -1) 
    { 
     reading.Consumption = rest.Substring(consumptionIndex + consumptionLength).Trim(); 
    } 

    readings.Add(reading); 
} 
2

您應該逐一解析這些值。 如果您有一個以「MeterNr」開頭的字符串,則應將其保存爲currentMeterNumber並進一步解析這些值。 否則,你可以用正則表達式解析值:

var dateRegex = new Regex(@"(?<=-\s)(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})"); 
var positionRegex = new Regex(@"(?<=position\s+)(\d+)"); 
var descriptionRegex = new Regex(@"(?<=\()(?<description>[^)]+)(?=\))"); 
var consuptionRegex = new Regex(@"(?<=consumption\s+)(?<consumption>(?<consumtionValue>\d+)\s(?<consumptionUom>\w+))"); 

我希望,你將能夠創建最終的算法,以及瞭解每個這些表達式的工作。最後一點可能是將它們全部組合成單個正則表達式。你應該自己做,以提高你的技能。

P.S .:網上有很多教程。

+0

輸入是基於數字模式和括號中的描述。不需要4種不同的正則表達式模式。 – 2011-12-13 11:54:39

+0

我認爲,輸入的形式是:'dataPrefix dataValue',如:「 - 」是日期前綴,「20111213」是日期本身。 「位置」是日期前綴,64699是位置本身。並且所有這些「名稱值」對都可以按照任意順序進行操作 –

+0

這是一個有效的假設,但在這種情況下,似乎輸入是特定/格式化的,並且它的來源不是正在鍵入的人。 – 2011-12-13 12:22:26

0
public static List<Reading> Parser(this string[] str) 
{ 
    List<Reading> result = new List<Reading>(); 
    string meterNr = ""; 
    Reading reading; 
    foreach (string s in str) 
    { 
     MatchCollection mc = Regex.Matches(s, "\\d+|\\((.*?)\\)"); 
     if (mc.Count == 1) 
     { 
      meterNr = mc[0].Value; 
      continue; 
     } 
     reading = new Reading() 
     { 
      MeterNr = meterNr, 
      Date = mc[0].Value, 
      Position = mc[1].Value, 
      ItemDescription = mc[2].Value.TrimStart('(').TrimEnd(')') 
     }; 
     if (mc.Count == 4) 
      reading.Consumption = mc[3].Value; 
     result.Add(reading);    
    } 
    return result; 
}