I'm currently passing a string, with multiple delimiters, to a method that I would like to initially split (at ~) into a string array, then each entry in the array (at |) to a dictionary ("key"="value").
~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987
~timestamp=Mar 1 2018 3:14PM|proc=procedure B|tran=transaction 2|rowCount=654
~timestamp=Mar 1 2018 3:14PM|proc=procedure C|tran=transaction 3|rowCount=321
I can accomplish the initial split into individual "rows"
~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987
with:
string result = <<long string>>;
string filepath = <<filepath variable>>;
string[] resultRows = result.Split('~');
try
{
foreach (string row in resultRows)
{
if (!File.Exists(filepath))
{
using (StreamWriter log = File.CreateText(filepath))
{
log.WriteLine(row);
}
}
else
{
using (StreamWriter log = File.AppendText(filepath))
{
log.WriteLine(row);
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
However, when I try to then parse each of those "rows" to a Dictionary, an error (Index was outside the bounds of the array) is thrown.
string result = <<long string>>;
string filepath = <<filepath variable>>;
string[] resultRows = result.Split('~');
Dictionary<string, string> dict = new Dictionary<string, string>();
try
{
foreach (string row in resultRows)
{
var results = row.Split('|').Select(s => s.Split(new[] { '=' }));
foreach (var item in results)
{
dict.Add(item[0], item[1]);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
I'm assuming that my expectations of the dictionary aren't correct -- I would like to see something along the lines of the following, for each "entry" in the Dictionary:
~timestamp=>Mar 1 2018 3:14PM, proc=>procedureA, tran=>transaction1, rowCount=>987
so that I can then write each line to a log file, where I can access the value for each key individually. If my understanding of how to set/get values in a dictionary are way off, is there a better way to accomplish this task?
Main problem was possible empty split-parts and after further splitting trying to access them via index in dict.Add(item[0], item[1]);
- if there is only one result its an index out of bounds exception.
Fixed version using IEnumerable.Aggregate() on your split-at ~
array:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
var dd = new Dictionary<string, Dictionary<string, string>>();
var data =
"~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987" +
"~timestamp=Mar 1 2018 3:14PM|proc=procedure B|tran=transaction 2|rowCount=654" +
"~timestamp=Mar 1 2018 3:14PM|proc=procedure C|tran=transaction 3|rowCount=321";
// splitting is done here:
var d = data
.Split(new[] { '~' }, StringSplitOptions.RemoveEmptyEntries)
.Aggregate(new List<Dictionary<string, string>>(),
(listOfDicts, part) =>
{
var key = Guid.NewGuid().GetHashCode().ToString();
listOfDicts.Add(new Dictionary<string, string>());
foreach (var p in part.Split(new[] { '|' },
StringSplitOptions.RemoveEmptyEntries))
{
// limit split to 2 parts if more then 1 = inside
var kvp = p.Split(new[] { '=' }, 2,
StringSplitOptions.RemoveEmptyEntries);
// either 2 or 1 is the result, handle both:
if (kvp.Count() == 2)
listOfDicts.Last()[kvp[0]] = kvp[1];
else
listOfDicts.Last()[kvp[0]] = null;
}
return listOfDicts;
});
// output:
foreach (var k in d)
{
Console.WriteLine();
foreach (var innerKvp in k)
{
Console.WriteLine(" " + innerKvp.Key + " " + innerKvp.Value);
}
}
Console.ReadLine();
}
}
Output: (list of dictionaries)
timestamp Mar 1 2018 3:14PM
proc procedure A
tran transaction 1
rowCount 987
timestamp Mar 1 2018 3:14PM
proc procedure B
tran transaction 2
rowCount 654
timestamp Mar 1 2018 3:14PM
proc procedure C
tran transaction 3
rowCount 321
The following function should be able to parse your inputs properly:
private static List<Dictionary<String,String>> ParseData(String data)
{
String[] entriesData = data.Split(new Char[] { '~' },StringSplitOptions.RemoveEmptyEntries);
List<Dictionary<String,String>> result = new List<Dictionary<String,String>>(entriesData.Length);
foreach (String entryData in entriesData)
{
String[] entryDataPairs = entryData.Split(new Char[] { '|' },StringSplitOptions.RemoveEmptyEntries);
Dictionary<String,String> entryResult = new Dictionary<String,String>(entryDataPairs.Length);
foreach (String entryDataPair in entryDataPairs)
{
String[] kvp = entryDataPair.Split(new Char[] { '=' },StringSplitOptions.RemoveEmptyEntries);
entryResult.Add(kvp[0], kvp[1]);
}
result.Add(entryResult);
}
return result;
}
The result produced by the following input string:
~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987~timestamp=Mar 1 2018 3:14PM|proc=procedure B|tran=transaction 2|rowCount=654~timestamp=Mar 1 2018 3:14PM|proc=procedure C|tran=transaction 3|rowCount=321
is:
--- ENTRY ---
timestamp = Mar 1 2018 3:14PM
proc = procedure A
tran = transaction 1
rowCount = 987
--- ENTRY ---
timestamp = Mar 1 2018 3:14PM
proc = procedure B
tran = transaction 2
rowCount = 654
--- ENTRY ---
timestamp = Mar 1 2018 3:14PM
proc = procedure C
tran = transaction 3
rowCount = 321
Give it a try by visiting this link !
Try something like this:
var dictionary = new Dictionary<string, string>();
foreach (var resultRow in resultRows)
{
if(!string.IsNullorEmpty(resultRow))
{
var rowItems = resultRow.Split('|').ToList();
dictionary.Add(rowItems.First(), string.Join("|", rowItems.Skip(1));
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.