-
Hallo,
ich brauche einen Parser weiß aber nicht ganz recht wie ich das anstellen soll, unzwar folgendes:
Code :1 2
(values (value1 50) (value2 0) (value3 6) (value4 80) (value5 70) (value6 10 20 30 40))
Ich möchte die werte folgendermaßen abrufen, z.b.was ja über ein dictionary möglich ist, als wert müsste ichCode :1
Value("value1").Item(0)erhalten. Mach ihn nunCode :1
50
müsste ich als wertCode :1
Value("value6").Item(2)erhalten. Ich hoffe ihr versteht wie ich das meine.Code :1
30
Ich hoffe ihr könnt mir weiterhelfen, das ding muss auch über mehrere zeilen arbeiten können und die anzahl von values ist dynamisch.
Peter86Geändert von Peter86 (03.01.10 um 02:46 Uhr)
-
02.01.10 21:45 #2
- Registriert seit
- Aug 2009
- Beiträge
- 11
Mir ist nicht ganz klar was du mit "das ding muss auch über mehrere zeilen arbeiten können und die anzahl von values ist dynamisch." meinst, aber vielleicht hilft dir der Denkanstoss ja weiter:
Code :1 2 3 4 5 6 7 8 9 10 11 12
Dictionary<string, List<int>> values = new Dictionary<string, List<int>>(); List<int> value1List = new List<int>(new int[] { 50 }); //... List<int> value6List = new List<int>(new int[]{10, 20, 30, 40}); values.Add("value1", value1List); values.Add("value6", value6List); int v1Item0 = values["value1"][0]; int v6Item2 = values["value6"][2];
-
Ich glaube er will einen Parser schreiben, der einen String in ein Dictionary verwandelt. Mir ist noch nicht ganz klar, wie der String aufgebaut ist, aber:
@Peter86:
Kennst du die IndexOf-Methode und Substring-Methode der String-Klasse? Damit kannst du nach öffnenden und schließenden Klammern suchen und dann den String so weit lesen, bis eine Ziffer kommt.hihi = -h²
-
03.01.10 02:00 #4
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Hi.
Regex böte sich auch an um an die Daten zu kommen.
Das folgende Beispiel prüft zuerst ob der gesamte Text dem Muster entspricht, und holt sich dann die Werte raus. Deswegen sind 2 reguläre Ausdrücke..
Mit meinen Regexes hab ich mich an dein Beispiel gehalten. Das gilt vorallem für "values1", "values2" etc.
"values" kann zwra anders lauten, aber die Zahl dahinter muss sein, ansonsten findet keine übereinstimmung statt.
Code csharp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
using System; using System.Collections.Generic; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { var result = Parse( "(values (value1 50) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20 30 40))"); foreach (string key in result.Keys) { Console.WriteLine("Name: {0}", key); for (int i = 0; i < result[key].Length; i++) Console.Write("{0}, ", result[key][i]); Console.WriteLine(); } Console.ReadLine(); } private static Regex validateRegex = new Regex( @"^\(values\ (?<valgroup>\((?<name>[a-zA-Z]+?\d+?\ )(?<values>(\d+\ )*)+?\)\ ?)+?\)$", RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); private static Regex matchRegex = new Regex( @"(?<valgroup>\((?<name>[a-zA-Z]+?\d+?\ )(?<values>(\d+\ )*)+?\)\ ?)+?", RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); private static Dictionary<string, int[]> Parse(string text) { var result = new Dictionary<string, int[]>(); if (!validateRegex.IsMatch(text)) return result; foreach (Match m in matchRegex.Matches(text)) { if (!m.Success) continue; string name = m.Groups["name"].Value; string[] stringvalues = m.Groups["values"].Value.Split(' '); int[] values = new int[stringvalues.Length]; for (int i = 0; i < stringvalues.Length; i++) values[i] = int.Parse(stringvalues[i]); result.Add(name, values); } return result; } }
lg,..With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Die sache liegt darin, der Parser soll nicht beschrängt sein sondern alles was in 2 klammern () ist herrausfiltern.
Um an die Klammern zu kommen hab ich schonmal was zusammen gewürfelt, Code ist zwar nicht so der Burner, aber es tut seinen dienst, vielleicht weiß ja wer wie mans besser macht.
Code vbnet:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
Module Module1 Sub main() Dim Line As String = "values (value1 50) (value2 0) (value3 6) (value4 80) " & _ "(value5 70) (value6 10 20 30 40)" Dim test As Dictionary(Of String, String()) = ParseLine(Line) For Each value In test Dim sb As New System.Text.StringBuilder For Each V In value.Value sb.Append(" " & V) Next Console.WriteLine("Beschreibung: {0} | Werte: {1}", value.Key, sb.ToString) Next Console.ReadLine() End Sub Function ParseLine(ByVal Line As String) Dim test As New List(Of Integer) Dim test1 As New List(Of Integer) Dim test2 As New List(Of Integer()) For i = 0 To Line.Length - 1 Select Case Line(i) Case "(" test.Add(i) Case ")" test1.Add(i) End Select Next For i = 0 To test.Count - 1 test2.Add(New Integer() {test.Item(i), test1.Item(i)}) Next Dim test3 As New Dictionary(Of String, String()) For Each c In test2 Dim s() As String = Line.Substring(c(0), c(1) - c(0) + 1).Replace("(", "").Replace(")", "").Split(" ") Dim werte(UBound(s) - 1) As String For i = 0 To UBound(s) - 1 werte(i) = New String(s(i + 1)) Next test3.Add(s(0), werte) Next Return test3 End Function End Module
Ich habe bei text die ( ganz vorne und die ) ganz hinten gelöscht weils sonst nicht richtig funktioniert hätte, normale müsste text so aussehen:
Dim text As String = "(values (value1 50) (value2 0) (value3 6) (value4 80) " & _
"(value5 70) (value6 10 20 30 40))"
Ich hab eine txt-Datei voller solcher zeilen wie oben, und die will ich komplett einlesen, manchmal gehören mehrere Zeilen, welche das sind sieht man wenn ganz am Anfang ein ( und ganz am ende ein ) ist und mein problem liegt jetzt darin rauszufinden welche Zeilen zusammen gehören, und dann jede zeile so einlesen wie der code es oben tut.Geändert von Peter86 (03.01.10 um 03:33 Uhr)
-
03.01.10 19:56 #6
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Mhmm.. nungut..
Oder hol dir zuerst aus deinem Text die Tokens raus, und die gehst du dann nach einander durch, merkst dir wo du gerade bist (Klammern zählen
), und behandelst die Daten dann entsprechend.
Hier (wieder) ein C# Beispiel:
Code csharp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
using System; using System.Collections.Generic; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { string text = "(values (value1 50) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20 30 40))"; var result = Parse(text); foreach (string key in result.Keys) { Console.WriteLine("Name: {0}", key); for (int i = 0; i < result[key].Length; i++) Console.Write("{0}, ", result[key][i]); Console.WriteLine(); } Console.ReadLine(); } private static Dictionary<string, int[]> Parse(string text) { var data = new Dictionary<string, int[]>(); bool outer = false; bool inner = false; bool first = false; string key = null; List<string> values = null; foreach (string token in Tokenize(text)) { switch (token) { case "(": if (outer) { inner = true; first = true; values = new List<string>(); } else outer = true; break; case ")": if (inner) { inner = false; int[] vals = new int[values.Count]; int t; for (int i = 0; i < vals.Length; i++) { if (int.TryParse(values[i], out t)) vals[i] = t; else throw new Exception("Token not a number"); } data.Add(key, vals); } else if (outer) outer = false; else throw new Exception("Unexpected token ')'"); break; default: if (!inner) break; if (first) { key = token; first = false; } else { values.Add(token); } break; } } return data; } private static IEnumerable<string> Tokenize(string text) { string token = ""; foreach (char c in text) { switch (c) { case ' ': case '\n': case '\r': if (token.Length > 0) yield return token; token = ""; break; case '(': case ')': if (token.Length > 0) yield return token; yield return c.ToString(); token = ""; break; default: token += c; break; } } } }
With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Danke, das funktioniert soweit ganz gut bis auf das ich kaum c# kann und es über Snippet Converter for .NET 2.0 convertiert vb.net nich ganz anehmen will, hab ich es einfach mal in c# eingefügt, doch wie mache ich es wenn ich nun mehrere zeilen einlesen will, z.b. will ich jetz mal folgendes einlesen:
Code :1 2 3 4 5 6 7 8 9 10
(values (value1 40) (value2 0) (value3 6) (value4 80) (value5 70) (value6 10 20)) (values (value1 70) (value2 0) (value3 6) (value4 80) (value5 70) (value6 10 20 30 40)) (values (value1 80) (value2 0) (value3 6) (value4 80) (value5 70) (value6 10 20 30)) (values (value1 90) (value2 0) (value3 6) (value4 40) (value5 70) (value6 10 20 30 20)) (values (value1 10) (value2 0) (value3 6) (value4 80) (value5 70) (value6 10 20 30 50))
Da gibt er mir nen fehler aus.
Wo der fehler liegt ist mir klar, doch bleiben die namen in jeder zeile gleich, nur die werte ändern sich.Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt.
Peter86Geändert von Peter86 (03.01.10 um 22:01 Uhr)
-
03.01.10 22:03 #8
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Tja, dann musst schon sagen, dass diese Namen mehrfach vorkommen können...
Da value1, value2 etc. als Schlüssel im Dictionary verwendet werden, darf es die nicht doppelt geben.
Also müssten die Daten jetzt anders gespeichert werden, dann geht aber..
..nicht mehr. (value1 ist ja nicht eindeutig)[...]Ich möchte die werte folgendermaßen abrufen, z.b.Code :1
Value("value1").Item(0)
was ja über ein dictionary möglich ist, als wert müsste ich[...]
Wie willst denn die Daten weiter verwenden? Pro Datensatz könnte man ein eigenes Dictionary zurückliefern. Möglich ist vieles, hängt halt ab wie du mit den Daten arbeiten willst/musst.
Mh ja, konvertieren kann man meinen Code nicht 1:1. "yield return" gibts nicht, da müsste man zuerst die Werte in eine Liste speichern, und dann die gesamte zurückliefern.
lg,..With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Ich brauch die werte in den Klammern nur einmal kurz auslesen und dann können sie schon wieder verworfen werden, also die werte in den klammern einmal einlesen, ausgeben und dann die nächste klammer das selbe tun. Also sozugsagen wie du schon meintes, jedes mal nen neues Dictionary, wobei das alte dann auch verworfen werden kann da es nicht mehr gebraucht wird.
-
03.01.10 22:49 #10
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Code csharp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
using System; using System.Collections.Generic; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { string text = "(values (value1 40) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20))" + "(values (value1 70) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20 30 40))" + "(values (value1 80) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20 30))" + "(values (value1 90) (value2 0) (value3 6) (value4 40) " + "(value5 70) (value6 10 20 30 20))" + "(values (value1 10) (value2 0) (value3 6) (value4 80) " + "(value5 70) (value6 10 20 30 50))"; var result = Parse(text); for (int i = 0; i < result.Count; i++) { Console.WriteLine("\r\n -- Zeile {0}", i); foreach (string key in result[i].Keys) { Console.WriteLine("Name: {0}", key); for (int j = 0; j < result[i][key].Length; j++) Console.Write("{0}, ", result[i][key][j]); Console.WriteLine(); } } Console.ReadLine(); } private static List<Dictionary<string, int[]>> Parse(string text) { var data = new List<Dictionary<string, int[]>>(); bool outer = false; bool inner = false; bool first = false; string key = null; List<string> values = null; Dictionary<string, int[]> currentData = new Dictionary<string, int[]>(); foreach (string token in Tokenize(text)) { switch (token) { case "(": if (outer) { inner = true; first = true; values = new List<string>(); } else outer = true; break; case ")": if (inner) { inner = false; int[] vals = new int[values.Count]; int t; for (int i = 0; i < vals.Length; i++) { if (int.TryParse(values[i], out t)) vals[i] = t; else throw new Exception("Token not a number"); } currentData.Add(key, vals); } else if (outer) { outer = false; if (currentData != null) data.Add(currentData); currentData = new Dictionary<string, int[]>(); } else throw new Exception("Unexpected token ')'"); break; default: if (!inner) break; if (first) { key = token; first = false; } else { values.Add(token); } break; } } return data; } private static IEnumerable<string> Tokenize(string text) { string token = ""; foreach (char c in text) { switch (c) { case ' ': case '\n': case '\r': if (token.Length > 0) yield return token; token = ""; break; case '(': case ')': if (token.Length > 0) yield return token; yield return c.ToString(); token = ""; break; default: token += c; break; } } } }
Jetzt kommt eine Liste von Dictionarys zurück. Jeder Listeneintrag stellt eine Zeile dar.
result[2]["value6"][1] wäre dann nach deinen letzten Daten 20
lg,..With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Danke Alex! Genau so brauch ich das.

Was ist eigentlich wenn eine Value mal keine nummer ist sondern ein String, kann man das noch schnell ändern das das auch geht oder wäre es nötig alles umzuschreiben?
Peter86Geändert von Peter86 (03.01.10 um 23:08 Uhr)
-
03.01.10 23:17 #12
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Dann ändert man überall Dictionary<string, int[]> zu <Dictionary<string, string[]>> und macht aus
dies:Code csharp:
Code csharp:1
string[] vals = values.ToArray();
Sollt alles gewesen sein.
lg,..With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Danke, jetzt funktioniert alles.

Code :1
Unexpected token ')'
Heißt, es fehlt eine klammer irgentwo oder?
Liegt warscheinlich daran, da manche zeilen kommentiert mit ; sind, wie kann ich diese zeilen ignoieren?Geändert von Peter86 (03.01.10 um 23:29 Uhr)
-
03.01.10 23:30 #14
- Registriert seit
- Aug 2001
- Ort
- Österreich, Stmk, Graz
- Beiträge
- 2.783
Ja, oder es ist eine zu viel.
Deine Eingabe sollte wenn möglich stimmen, die Fehlerbehandlung ist nicht wirklich umfangreich.
Edit: Könntest eine vollständige Datei zeigen? *g* Vielleicht gibts ja noch weitere Überaschungen...With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
Aaron Satie
Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
Captain Jean-Luc Picard, Stardate ~41294.5
Tutorials.de chattet. Hier gibts auch .net Support ^^
Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de
(moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions
-
Sind halt mehrere dateien die ich einlesen will.
Code :1
(values (values1 2) (values2 0) (values3 6) (values4 10 20 30 40))
Code :1
(values (values1 22) (values2 (550 40 111) (1 2 3)))
Das sind die Formate die ich einlesen müsste, wobei das erste ja auch geht.
Geändert von Peter86 (04.01.10 um 00:05 Uhr)
Ähnliche Themen
-
mathematische klammern in php
Von rene5 im Forum PHPAntworten: 10Letzter Beitrag: 13.08.10, 20:55 -
Eckige Klammern: Quot
Von XEMO im Forum PHPAntworten: 7Letzter Beitrag: 14.07.05, 23:12 -
Korrespondierende Klammern
Von Krümel im Forum VisualStudio & MFCAntworten: 1Letzter Beitrag: 29.06.04, 08:39 -
!ereg und eckige klammern :/
Von smilex im Forum PHPAntworten: 4Letzter Beitrag: 08.02.04, 14:12 -
mit css klammern um link bei hover
Von toxical im Forum CSSAntworten: 14Letzter Beitrag: 13.12.01, 14:29



1Danke

Zitieren


Login





