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

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.

Related

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]);

Parse String with delimiters to dictionary

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);

replacing data in between specific characters

I have a string which has some keys between <<>>.
string s = "<p>Hi <<USER>>,<br/>How are you doing<br/>Regards,<br/><<SENDER>></p>";
I want to first fetch the key names USER and SENDER in a list which i did by:
var keys = new List<string>();
foreach (Match match in Regex.Matches(s, #"<<(.*?)>>"))
{
keys.Add(match.Groups[1].Value);
}
List<string> values= new List<string>(){"John","Team"};
After we get the keys,i want to replace these keys by another list(named values here) which has the values for these keys and want the result as:
string s = "<p>Hi John,<br/>How are you doing<br/>Regards,<br/>Team</p>";
The string s can be anything and the no of keys and their values could also vary but the keys will always be enclosed in between <<>>
As suggested by #AlexBell, you could simply use the String.Replace() method.
Further, it's more convenient to declare a collection of placeholder/value pairs, like so:
string s = "<p>Hi <<USER>>,<br/>How are you doing<br/>Regards,<br/><<SENDER>></p>";
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("<<USER>>", "Jhon");
dictionary.Add("<<SENDER>>", "Team");
StringBuilder text = new StringBuilder(s);
foreach (var entry in dictionary)
{
text.Replace(entry.Key, entry.Value);
}
Console.WriteLine(text.ToString());
This function will perform the replacements that you ask for, using Regex.Replace:
public static string ParseTemplate(string template, string username, string senderName)
{
template = Regex.Replace(template, #"<<USER>>", username);
return Regex.Replace(template, #"<<SENDER>>", senderName);
}
Example:
string s = "<p>Hi <<USER>>,<br/>How are you doing<br/>Regards,<br/><<SENDER>></p>";
ParseTemplate(s, "John", "Team").Dump();
Output:
<p>Hi John,<br/>How are you doing<br/>Regards,<br/>Team</p>
You can call this in a loop over your dictionary or list of names.
Your business logic is a bit unclear, so based on just qualified guess, you can apply standard .NET/C# String.Replace Method (String, String)
(re:https://msdn.microsoft.com/en-us/library/fk49wtc1%28v=vs.110%29.aspx), for example:
string s = "<p>Hi <<USER>>,<br/>How are you doing<br/>Regards,<br/><<SENDER>></p>".Replace("<USER>", "John").Replace("<SENDER>", "Team");
Hope this may help.
//First we have lists of values (users) and senders
List<string> values= new List<string>(){"John","Team"};
List<string> senders = new List<string>(){"John","Team"};
//Then we can join that list using string.join
var allUsers = string.Join(",", values);
var allSender = string.Join(",", senders);
//Next we will be replacing it in our string
var namedString = Regex.Replace(string, #"<<USER>>", allUsers);
var output = Regex.Replace(namedString , #"<<SENDER>>", allSender);

c# - regex to find a string that comes after = [duplicate]

This question already has answers here:
regex to find a string that comes after =
(6 answers)
Closed 9 years ago.
So I asked this question before and said I wanted it in javascript but realized later on that it's unecessary data being sent. So it would be great if anybody could help me solve the same thing in C#
What I need is to get several properties out of a string.
The string will look something like:
str = "car[brand=saab][wheels=4]";
There can be more or fewer properties.
I need everything before the first [] in 1 variable.
Then I need each property and its value in a variable.
Easiest way to understand what I want is probably to check my previous question and the answer that solved it :)
I used the regex(slightly different) in your previous question.
string input = "car[brand=saab][wheels=4]";
string product = "";
Dictionary<string, string> props = new Dictionary<string, string>();
foreach (Match m in Regex.Matches(input, #"^(\w+)|\[(\w+)=(.+?)\]"))
{
if (String.IsNullOrEmpty(product))
product = m.Groups[1].Value;
else
props.Add(m.Groups[2].Value, m.Groups[3].Value);
}
try this regex:
(.+?)(\[.+?\])+
and a sample code:
var inputString = "car[brand=saab][wheels=4]";
var pattern = #"(?<v1>.+?)(?<v2>\[.+?\])+";
var v1 = Regex.Match(inputString, pattern).Groups["v1"].Value;
Dictionary<String, String> list = new Dictionary<String, String>();
foreach (Capture capture in Regex.Match(inputString, pattern).Groups["v2"].Captures)
{
var sp = capture.Value.Split('=');
list.Add(sp[0], sp[1]);
}
explain:
(?<name>subexpression)
Captures the matched subexpression into a named group.
You can do this
var lst=Regex.Matches(input,#"(\w+)((?:\[.*?\])+)")
.Cast<Match>()
.Select(x=>new
{
name=x.Groups[1].Value,
value=Regex.Matches(x.Groups[2].Value,#"(?<=\[).*?(?=\])")
.Cast<Match>()
.Select(x=>new
{
name=x.Groups[0].Value.Split('=')[0],
value=x.Groups[0].Value.Split('=')[1]
})
});
Now you can iterate over lst like this
foreach(var parent in lst)
{
parent.name;//car
foreach(var pairs in parent.value)
{
pairs.name;//brand,wheels
pairs.value;//ferrari,4
}
}
So,for input car[brand=a][wheels=4]cycle[brand=b][wheels=2]
Output would be like
car
brand,a
wheels,4
cycle
brand,b
wheels,2
Without regex:
string input = "car[brand=saab][wheels=4]";
var query = from s in input.Replace("]", "").Split('[')
let vars = s.Split('=')
let name = vars[0]
let value = vars.Length > 1 ? vars[1] : ""
select new {Name = name, Value = value};
string firstVar = query.First().Name;
Dictionary<string, string> otherVars = query
.Skip(1)
.ToDictionary(v => v.Name, v => v.Value);
You can access your variables in the dictionary like this string brand = otherVars["brand"]
Since you already have an answer using regex and your comments state it doesn't have to be with a regex, I'll offer an alternative:
The code is
string str = ("car[brand=saab][wheels=4]");
int i = str.IndexOf("[");
string[] details =str.Substring(i).Replace("]","").Split('[');
string name = str.Substring(0, i);
string brand = details[1].Split('=')[1];
string wheels = details[2].Split('=')[1];
This approach assumes the data is always going to be in the same format though; you may need some validation in there depending on your needs...

Categories