Parse String with delimiters to dictionary - c#

I have a string formated so:
string-int,string-int,string-int
The data will always be as above, what i need to accomplish is splitting each string-int value into a dictionary. Does anyone have an efficient solution to accomplish this?
As i understand it directly splitting the string by the ',' then splitting each result by the '-' into a dictionary is ineffcient.

If you are absolutely assured that all data is correct you can use following:
split source string to the string[] by "," symbol;
for each element split it by "-" symbol;
for each resulted element (of string[][]) convert it to dictionary pair. Use first element [0] as a key and cast second element [1] to integer as a value;
Dictionary<string, int> dictionary = sourceString
.Split(',')
.Select(element => element.Split('-'))
.ToDictionary(pair => pair[0], pair => int.Parse(pair[1]));

Try following .
var input = "string-1,string2-2,string3-3";
var splittedByComma = input.Split(',').ToList();
var dictionary = new Dictionary<string, int>();
splittedByComma.ForEach(sp => dictionary.Add(sp.Split('-')[0], int.Parse(sp.Split('-')[1])));

static Dictionary<string, int> convert(string s)
{
var t = new Dictionary<string, int>();
t.Add(s.Split('-')[0], System.Convert.ToInt32(s.Split('-')[1]));
return t;
}
var t = "\"test\"-123,\"test\"-123";
var d = t.Split(',').Select(convert);

Related

Can we convert the style attribute value into a dictionary in C#

I need to update the style attribute values based on some calculations made in the server side, I have passed the style attribute value from client to server as string, now i need to convert it to key value pair so that i can update the style based in the key but can't convert it. any suggestions please.
value sent to server
"width:100%;height:100%;"
I need to convert this value to a dictionary in key value pairs so i can update the values based on keys or any alternate solution.
var style = "width:100%;height:70%;";
var dic = style.Split(";", StringSplitOptions.RemoveEmptyEntries)
.ToDictionary(k => k.Split(":")[0], k => k.Split(":")[1]);
// Output:
// Key: width, Value: 100%
// Key: height, Value: 70%
Or, as #DmitryBychenko offered (the only thing he forgot is to remove empty entries):
var dic = style.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Split(":"))
.ToDictionary(k => k[0], k => k[1]);
Or even Regex :)
var dic = Regex.Matches(style, "(.+?):(.+?);")
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[2]);
Find the working code of a consoleapp with the separated function that returns the dict from your string, not using LINQ (apart from the .Tolist()) so more readable and understandable for beginners maybe:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp4 {
class Program {
static void Main(string[] args) {
string mystr = "width:100%;height:100%;";
IDictionary<string, string> myDict = getDictFromString(mystr);
foreach (KeyValuePair<string, string> element in myDict) {
Console.WriteLine("Key = {0}, Value = {1}", element.Key, element.Value);
}
Console.ReadLine();
}
static private IDictionary<string, string> getDictFromString(string stringArgument) {
string[] mysubStr = stringArgument.Split(';');
IDictionary<string, string> myResultantDict = new Dictionary<string, string>();
foreach (string substr in mysubStr.ToList()) {
if (!String.IsNullOrEmpty(substr)) {
string key = substr.Split(':')[0];
string value = substr.Split(':')[1];
myResultantDict.Add(new KeyValuePair<string, string>(key, value));
}
}
return myResultantDict;
}
}
}

Good approach to sorting strings which contain number ie test 1, test10, test2

I am using C#, .NET 4.7
I have 3 strings ie.
[test.1, test.10, test.2]
I need to sort them to get:
test.1
test.2
test.10
I may get other strings like
[1test, 10test, 2test]
which should produce:
1test
2test
10test
using same approach.
Thoughts?
Thanks in advance.
You could use Parse the number using Regex and then sort the string. For example,
Regex re = new Regex(#"\d+");
var result = strArray.Where(x=>re.Match(x).Success)
.Select(x=> new { Key = int.Parse(re.Match(x).Value),Value = x})
.OrderBy(x=>x.Key).Select(x=>x.Value);
Where strArray is the collection of strings.
Please note in the above case, you are ignoring string which doesn't have a numeric part (as it wasn't described in OP). The numeric part of string is parsed using Regex, which is then used for sorting the collection.
Example,
Input
var strArray = new string[]{"1test", "10test", "2test"};
Output
1test
2test
10test
Input
var strArray = new string[]{"test.1", "test.10", "test.2"};
Outpuyt
test.1
test.2
test.10
For your first array you can do
var array = new[] { "test.1", "test.10", "test.2" };
var sortedArray = array.OrderBy(s => int.Parse(s.Substring(5, s.Length - 5)));
For the second array
var array = new[] { "1test", "2test", "10test" };
var sortedArray = array.OrderBy(s => int.Parse(s.Substring(0, s.Length - 4)));
Try this code. It uses SortedDictionary which always sort it's items by key when they are inserted.
static void Main(string[] args)
{
SortedDictionary<int, string> tuples = new SortedDictionary<int, string>();
string[] stringsToSortByNumbers = { "test.1", "test.10", "test.2" };
foreach (var item in stringsToSortByNumbers)
{
int numeric = Convert.ToInt32(new String(item.Where(Char.IsDigit).ToArray()));
tuples.Add(numeric, item);
}
foreach (var item in tuples)
{
Console.WriteLine(item.Value);
}
Console.ReadKey();
}

Find specific part of string based on condition

I have below comma separated string. This string contains relation which is needed in the application for processing.
string userInputColRela = "input1:Student_Name, input2:Student_Age";
Now, i need to extract Student_Name if i provide input as input1 and Student_Age if the input provided is input2.
How can i achieve this? I know i can go with looping but that will be a little lengthy solution, what is other way round?
You could parse the input string by splitting firstly on the comma, then again on the semi-colon to get the key-value pairs contained in it in dictionary form. For example:
string userInputColRela = "input1: Student_Name, input2: Student_Age";
var inputLookup = userInputColRela
.Split(',')
.Select(a => a.Split(':'))
.ToDictionary(a => a[0].Trim(), a => a[1].Trim());
var studentName = inputLookup["input1"];
If your strings are always in the format input1:Student_Name, input2:Student_Age then probably you can use a Dictionary<k,v> and Split() function like
string userInputColRela = "input1:Student_Name, input2:Student_Age";
string input = "input1";
var args = userInputColRela.Split(',');
Dictionary<string, string> inputs = new Dictionary<string, string>();
foreach (var item in args)
{
var data = item.Split(':');
inputs.Add(data[0], data[1]);
}
Console.WriteLine(inputs[input]);

Making a List<string> from Dictionary<string, string>

I was wondering if it were possible to make a list from the dictionary values where the key is a specified value?
The dictionary would like this:
Sidcup - DPC1
Sidcup - DPC2
Blackheath - DPC3
Blackheath - DPC4
Bexleyheath - DPC5
In fact, I'm not entirely implementing a Dictionary as above is a good idea. Here is its implementation:
DataSet ds = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID);
if (ds.Tables.Count > 0)
{
DataTable dtDPCs = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID).Tables[0];
Dictionary<string, string> preliminaryList = new Dictionary<string, string>();
if (dtDPCs.Columns.Contains("DPCNumber") && dtDPCs.Columns.Contains("BranchName"))
foreach (DataRow dataRow in dtDPCs.Rows)
{
preliminaryList.Add(dataRow["BranchName"].ToString(), dataRow["DPCNumber"].ToString());
}
I have the following code: (Excuse the last line, its just so you have an idea of what I'm trying to do).
foreach (string branch in branchNames)
{
string subfolder = System.IO.Path.Combine(saveLocation, branch);
System.IO.Directory.CreateDirectory(subfolder);
List<string> certificateList = new List<string>();
certificateList.Add(DPCNumber in preliminaryList where Key = branch);
}
In the above the branch is the key from the Dictionary. I need to iterate through because it needs to create a new folder and then do something with the certificateList I am creating.
Sure:
private static void TestZip()
{
Dictionary<string, string> stringstringdic = new Dictionary<string, string>();
stringstringdic.Add("1", "One");
stringstringdic.Add("2", "Two");
stringstringdic.Add("3", "Three");
stringstringdic.Add("4", "Four");
stringstringdic = stringstringdic.Where(pair => pair.Key != "1")
.ToDictionary(pair => pair.Key, pair => pair.Value);
List<string> stringlist = stringstringdic.Keys.Concat(stringstringdic.Values).ToList();
foreach (string str in stringlist)
{
Console.WriteLine(str);
}
}
//Output:
//2
//3
//4
//Two
//Three
//Four
Of course, you'll have to change the Where clause to reflect your real need.
If I understood you right, it's like .Where(pair => pair.Key == branch)
If I understand you correctly you want to add the value based on a key to a separate List?
certificateList.Add(preliminaryList[branch])
This is simplified as I really need to see the declaration of preliminaryList to know how DPCNumber fits into all of it. Could it be...
certificateList.Add(preliminaryList[branch].ToString())
To simply create a list of keys you can do the following.
var dictionary = new Dictionary<string, string>();
dictionary.Add("key1", "value1");
dictionary.Add("key2", "value2");
dictionary.Add("key3", "value3");
dictionary.Add("key4", "value4");
dictionary.Add("key5", "value5");
var list = dictionary.Keys.ToList();
This should give you a list with values "key1", "key2", "key3", "key4", "key5".
You can put a where clause in to filter out certain keys. The following gives all keys which contain a "2" (random example), resulting in just "key2".
var filteredList = dictionary.Keys.Where(key => key.Contains("2")).ToList();
Edit:
To get a value given a specific key.
string value = dictionary["key1"];
Note, the key is a dictionary must be unique, so for a given key you will only ever get a single value back and not a list of values.

How can you change a ";" seperated string to some kind of dictionary?

I have a string like this:
"user=u123;name=Test;lastname=User"
I want to get a dictionary for this string like this:
user "u123"
name "Test"
lastname "User"
this way I can easely access the data within the string.
I want to do this in C#.
EDIT:
This is what I have so far:
public static Dictionary<string, string> ValueToDictionary(string value)
{
Dictionary<string, string> result = null;
result = new Dictionary<string, string>();
string[] values = value.Split(';');
foreach (string val in values)
{
string[] valueParts = val.Split('=');
result.Add(valueParts[0], valueParts[1]);
}
return result;
}
But to be honest I really think there is a better way to do this.
Cheers,
M.
You can use LINQ:
var text = "user=u123;name=Test;lastname=User";
var dictionary = (from t in text.Split( ";".ToCharArray() )
let pair = t.Split( "=".ToCharArray(), 2 )
select pair).ToDictionary( p => p[0], p => p[1] );
Split the string by ";".
Iterate over every element in the resulting array and split every element by "=".
Now;
dictionary.add(element[0], element[1]);
I Hope I made it clear enough.
Dictionary<string, string> d = new Dictionary<string, string>();
string s1 = "user=u123;name=Test;lastname=User";
foreach (string s2 in s1.Split(';'))
{
string[] split = s2.Split('=');
d.Add(split[0], split[1]);
}
var dictionary = new Dictionary<string, string>();
var linedValue = "user=u123;name=Test;lastname=User";
var kvps = linedValue.Split(new[] { ';' }); // you may use StringSplitOptions.RemoveEmptyEntries
foreach (var kvp in kvps)
{
var kvpSplit = kvp.Split(new[] { '=' });
var key = kvpSplit.ElementAtOrDefault(0);
var value = kvpSplit.ElementAtOrDefault(1);
dictionary.Add(key, value);
// you may check with .ContainsKey if key is already persistant
// you may check if key and value with string.IsNullOrEmpty
}
If you know for sure that there are no separator chars in your input data, the following works
string input = "user=u123;name=Test;lastname=User";
string[] fragments = input.Split(";=".ToArray());
Dictionary<string,string> result = new Dictionary<string,string>()
for(int i=0; i<fragments.Length-1;i+=2)
result.Add(fragments[i],fragments[i+1]);
It might perform slightly better than some of the other solutions, since it only calls Split() once. Usually I would go for any of the other solutions here, especially if readability of the code is of any value to you.
I think I would do it like this...
String s = "user=u123;name=Test;lastname=User";
Dictionary<string,string> dict = s.ToDictionary();
The implementation of ToDictonary is the same as yours except that I would implement it as an extension method. It does look more natural.

Categories