0

I'm stucked on my next problem.

I read a line from a textfile containing like:

(("ITEM" "05") ("NUMBER" "1") ("DESCRIPTION" "*RECHTE INSTEEKKOP. 1/4\"-8MM") ("ARTICLENUMBER" "S110010000104"))

In Lisp this is a List and for retrieving the value of eg ITEM in Lisp:

(cadr (assoc "ITEM" str))

This gives 05

How can I achieve this simply in C#?

Martin
  • 16,093
  • 1
  • 29
  • 48
Marco
  • 3
  • 2
  • 6
    There is no *"simply"*, this is not a naively *serializable* file in *.net*. Firstly you will need to *read* the file, *parse* the file into a *dictionary*, then return the *value* you want by *key* – TheGeneral Feb 07 '20 at 09:59
  • Answers for this [question](https://stackoverflow.com/questions/3051254/parsing-lisp-s-expressions-with-known-schema-in-c-sharp) should help. And this [article](https://rosettacode.org/wiki/S-Expressions#C.23). – BWA Feb 07 '20 at 10:11

2 Answers2

1

You could use Regex to parse the value and then fetch the result. For example,

var valueCollection = Regex.Matches(datastring,@"\(""(?<Key>.+?(?=""))""\s+""(?<Value>.+?(?=""))""\)")
                                 .Cast<Match>()
                                .Select(x=>new {Key = x.Groups["Key"].Value,Value = x.Groups["Value"].Value,});

This would provide you with collection as the following

enter image description here

You could now fetch the Value where Key is equal to "ITEM" using Linq.

var itemValue = valueCollection.First(x=>x.Key=="ITEM").Value;

Alternatively, you could convert the string to a Dictionary as

var valueCollection = Regex.Matches(datastring,@"\(""(?<Key>.+?(?=""))""\s+""(?<Value>.+?(?=""))""\)")
                                 .Cast<Match>()
                                 .ToDictionary(x=>x.Groups["Key"].Value,y=>y.Groups["Value"].Value);

You could now parse the required ITEM value as

var itemValue = valueCollection["ITEM"];

Update Based on comment

In case you expect empty values, you could use the following regex pattern.

@"\(""(?<Key>.+?(?=""))""\s+""(?<Value>.*?(?=""))""\)"
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • Nice work, though what if the list has an escaped `)` ? – TheGeneral Feb 07 '20 at 10:21
  • @Marco Glad it helped. Kindly mark it as Answer/Helpful if it helped in resolving your issue – Anu Viswan Feb 07 '20 at 13:11
  • I got an error when value is "". In next line "DIMENSIONS" is empty. *(("ITEM" "01") ("NUMBER" "4") ("DESCRIPTION" "LUIK TEMA Ø 450") ("DIMENSIONS" "") ("REMARKS" "VOLGENS S000001-0004") ("ABS" "S") ("CADID" "32A96") ("ARTICLENUMBER" "S000001-0004") ("ZAAGCODE" "") ("Snijden" ""))* – Marco Feb 10 '20 at 14:58
  • @Anu Thanks, works fine! I try to understand regex.matches but no change. So I give up and just copy paste it in my code and it works. I will try again to understand later. – Marco Feb 13 '20 at 06:59
0

Another approach is using Split function

string values = "((\"ITEM\" \"05\") (\"NUMBER\" \"1\") (\"DESCRIPTION\" \" * RECHTE INSTEEKKOP. 1 / 4\" - 8MM\") (\"ARTICLENUMBER\" \"S110010000104\"))";

var keyValuePairs = values.Split(new[] { "(", ")", " (", ") " }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(s => s.Split(new[] { ' ' }, 2))
                    .ToDictionary(x => x[0].ToString(), x => x[1].ToString());

Output

enter image description here

Krishna Varma
  • 4,238
  • 2
  • 10
  • 25