splitting string in dictionary - c#

How do I split the following string
string s = "username=bill&password=mypassword";
Dictionary<string,string> stringd = SplitTheString(s);
such that I could capture it as follows:
string username = stringd.First().Key;
string password = stringd.First().Values;
Please let me know. Thanks

You can populate the dictionary list like so:
Dictionary<string, string> dictionary = new Dictionary<string, string>();
string s = "username=bill&password=mypassword";
foreach (string x in s.Split('&'))
{
string[] values = x.Split('=');
dictionary.Add(values[0], values[1]);
}
this would allow you to access them like so:
string username = dictionary["username"];
string password = dictionary["password"];
NOTE: keep in mind there is no validation in this function, it assumes your input string is correctly formatted

It looks like you are trying to parse a query string - this is already built in, you can use HttpUtility.ParseQueryString() for this:
string input = "username=bill&password=mypassword";
var col = HttpUtility.ParseQueryString(input);
string username = col["username"];
string password = col["password"];

I think something similar to this should work
public Dictionary<string, string> SplitTheStrings(s) {
var d = new Dictionary<string, string>();
var a = s.Split('&');
foreach(string x in a) {
var b = x.Split('=');
d.Add(b[0], b[1]);
}
return d;
}

var splitString = "username=bill&password=pass";
var splits = new char[2];
splits[0] = '=';
splits[1] = '&';
var items = splitString.Split(splits);
var list = new Dictionary<string, string> {{items[1], items[3]}};
var username = list.First().Key;
var password = list.First().Value;
this my also work

If Keys will not repeat
var dict = s.Split('&').Select( i=>
{
var t = i.Split('=');
return new {Key=t[0], Value=t[1]};}
).ToDictionary(i=>i.Key, i=>i.Value);
If Keys can repeat
string s = "username=bill&password=mypassword";
var dict = s.Split('&').Select( i=>
{
var t = i.Split('=');
return new {Key=t[0], Value=t[1]};}
).ToLookup(i=>i.Key, i=>i.Value);

The other answers are better, easier to read, simpler, less prone to bugs, etc, but an alternate solution is to use a regular expression like this to extract all the keys and values:
MatchCollection mc = Regex.Matches("username=bill&password=mypassword&","(.*?)=(.*?)&");
Each match in the match collection will have two groups, a group for the key text and a group for the value text.
I am not too good at regular expressions so I don't know how to get it to match without adding the trailing '&' to the input string...

Related

C# .net regex extracting a string from within a string

I have a string output that looks like this:
ID = GC5c.U.feab4bc5-8-92e-c486eaddddf8
AESKEY1 = efbf5c9db259e345c205b0da27f6fb459D
AESKEY2 = ea85af9f1e5f42ff4fe8b9f07e7dcebc68
DESKEY1 = 6388a9e1a2fc8981189f0f412ae4e8
ID = JNPa.T.71664548-82-be2-a51aadd4a6f3
AESKEY1 = 37af9242c8879414e420f46903c16adebd3
AESKEY2 = 1259a1f6f6da03cb3984a117ca617d9ff73
DESKEY1 = 9547dc08db70cb95789f3a59e5c6adebd31
How can I iterate through the ID(s) of this list and obtain the values within the string?
Open the file, iterate through each line, and put it into a Dictionary<string, string>
Dictionary<string, string> data = new Dictionary<string, string>();
using(StreamReader reader = new StreamReader("C:/YourFilePath.txt"))
{
while (reader.Peek() >= 0)
{
string[] line = reader.ReadLine().Split('=');
data.Add(line[0].TrimEnd(), line[1].TrimStart());
}
}
UPDATE: Note that this solution is using Dictionary, and so it does not allow duplicate keys. If you need to duplicate keys, I would suggest changing this solution for a List<KeyValuePair<string, string>>. The code will get a little dirtier by the way:
List<KeyValuePair<string, string>> data = new List<KeyValuePair<string, string>>();
using(StreamReader reader = new StreamReader("C:/YourFilePath.txt"))
{
while (reader.Peek() >= 0)
{
string[] line = reader.ReadLine().Split('=');
data.Add(new KeyValuePair(line[0].TrimEnd(), line[1].TrimStart()));
}
}
I am not sure Regex is the best suited for this scenario, however, please find below a solution using it with a named group "id".
var regex = new Regex(#"id.*=\s*(?<id>.+)", RegexOptions.IgnoreCase);
var input = #"ID = Gs3c.H.feab4bc5-6c00-4ee8-9e2e-c486eaddddf8
AESKEY1 = efbf5c9db259e345c205b0da27f6fb459D
AESKEY2 = ea85af9f1e5f42ff4fe8b9f07e7dcebc68
DESKEY1 = 6388a9e1a2fc8981189f0f412ae4e8
ID = JNPa.T.71664548-82-be2-a51aadd4a6f3
AESKEY1 = 37af9242c8879414e420f46903c16adebd3
AESKEY2 = 1259a1f6f6da03cb3984a117ca617d9ff73
DESKEY1 = 9547dc08db70cb95789f3a59e5c6adebd31";
var ids = regex.Matches(input).Cast<Match>().Select(m => m.Groups["id"]);
Here is the Regex test: Regex test
NicoRiff's suggestion of using regular parsing into a Dictionary is the way to go. Here's the obligatory LINQ-based approach:
var data = File.ReadLines("C:/your/file/path.txt")
.Select(l => l.Split('='))
.ToDictionary(k => k[0], v => v[1]);
EDIT: As Nico pointed out, when the dictionary is going to contain duplicate keys, then a dictionary won't work. However, you can still use LINQ to automatically arrange the dictionary so that the ID field of your source text is the key instead of the field names. For example, you can use the following:
var data = File.ReadLines("C:/your/file/path.txt")
.Where(l => !String.IsNullOrEmpty(l))
.Select((l, i) => new { ID = i / 4, Value = l.Split('=') })
.GroupBy(x => x.ID)
.Select(g => new { ID = g.First().Value[1].Trim(), Values = g.ToDictionary(k => k.Value[0].Trim(), v => v.Value[1].Trim()) })
.ToDictionary(k => k.ID, v => v.Values);
Afterwards, you can iterate through data to get your fields:
foreach (var d in data.Values)
{
string id = d["ID"];
string aesKey1 = d["AESKEY1"];
string aesKey2 = d["AESKEY2"];
string desKey1 = d["DESKEY1"];
}
If you like to put the data into a dictionary like: Dicationary<string, Dictionary<string,string>>
Where the key of the main dictionary is the value of ID, and the internal dictionaries are the values that follows, then the following would do it:
string[] lines = input.Split('\n');
var myDict = new Dictionary<string, Dictionary<string,string>>();
var currentKey = "";
foreach (string[] keyVal in lines.Where(line=>!string.IsNullOrWhiteSpace(line))
.Select(line => line.Split('=')))
{
if (keyVal[0].StartsWith("ID"))
{
currentKey = keyVal[1].Trim();
myDict.Add(currentKey, new Dictionary<string, string>());
}
else
{
myDict[currentKey].Add(keyVal[0].Trim(), keyVal[1].Trim());
}
}
The Regex would look like so:
#"^ID\s+=\s+(.+)$"
You can test it on Regex101 and Rextester

String data to be converted to Dictionary

I have a String
string data = "[City, Delhi]&[State, DL]&[Country, IN]";
from which I want a dictionary.
The approach I thought was
Split on "&"
In the resulting Array, parse each element
2.1 Replace "[" and "]"
2.2 Insert into the Dictionary
I hate this approach because my string already has "[" and "]" and I should be able to add it directly to Dictionary.
This is a good use case for regular expressions.
var d = Regex.Matches(data, #"\[(?<k>[^,]+), (?<v>[^]]+)\]")
.OfType<Match>()
.ToDictionary(m => m.Groups["k"].Value, m => m.Groups["v"].Value);
The approach you describe is probably as good as it's going to get.
A naive implementation (without error handling) would be:
var pairs = data.Split('&');
var dict = new Dictionary<string, string>();
foreach (var pair in pairs)
{
var parts = pair.Split(',');
dict.Add(
parts[0].TrimStart('['),
parts[1].TrimStart().TrimEnd(']'));
}
Or, using a regular expression to obtain the keys and values:
string data = "[City, Delhi]&[State, DL]&[Country, IN]";
var pairs = data.Split('&');
var dict = new Dictionary<string, string>();
var regex = new System.Text.RegularExpressions.Regex(#"\[(?<key>.*), (?<value>.*)\]");
foreach (var pair in pairs)
{
var match = regex.Match(pair);
// TODO: Error if match.Success == false ?
dict.Add(match.Groups["key"].Value, match.Groups["value"].Value);
}
You can try this using linq
string data = "[City, Delhi]&[State, DL]&[Country, IN]";
string[] arr = data.Replace("[", "").Replace("]", "").Split('&');
var dict = arr.ToList().ToDictionary(x => x.Split(',')[0], x => x.Split(',')[1]);
Try this...
private static void Splitter()
{
string data = "[City, Delhi]&[State, DL]&[Country, IN]";
Dictionary<string,string> dOutput = new Dictionary<string,string>();
string[] sArr = data.Split('&');
var v = from p in sArr
select p.Replace("[", "").Replace("]", "").Split(',');
var v2 = (from p in v
select p).ToDictionary(item => item[0], item => item[1]);
Console.WriteLine(v2.Count());
}
v2 is a dictionary object...

How to split and take multiple strings from a url in c#?

I have a string looking something like this:
/Gender=&Age=&Query=&Orgrimmar+l%C3%A4n=01&Stormwind+l%C3%A4n=07&Undercity+l%C3%A4n=09&Pag
I want a list of string with "Orgrimmar", "Stormwind" and "Undercity". How is this possible so that it splits AFTER Query and between & and + in order so that we avoid getting a string like this "Orgrimmar+l%C3%A4n=01&Stormwind".
Let us assume that we don't know the name of the strings.. :)
Updated, i still don't seem to get it to work. I have added a list of counties that i can use to validate this. However i still find it hard in this case. countyList is used to validate that the counties/cities in the url matches a pre-existing Collection.
var countyQuery = Request.Url.Query;
var counties = this._locationService.GetAllCounties();
List<string> countyList = new List<string>();
List<string> selectedCountiesList = new List<string>();
foreach (var i in counties)
{
countyList.Add(i.Name);
}
Regex r = new Regex(#"&(.+?)\+");
MatchCollection mc = r.Matches(countyQuery);
foreach (Match curMatch in mc)
{
if (countyList.Contains(curMatch.Groups[1].Value))
{
selectedCountiesList.Add(curMatch.Groups[1].Value);
}
}
return selectedCountiesList;
Changed url to be/?Gender=&Age=&Query=&county=13&county=08&county=01&Page=1
where 13, 08, 01 and so on is Id of the counties
The final solution was:
var selectedCountyQuery = Request.QueryString
//CountySearch = "county"
[QueryStringParameters.CountySearch];
List countyList = new List();
List<string> selectedCounties = new List<string>();
if (!string.IsNullOrEmpty(selectedCountyQuery))
{
var selectedCountiesArray = selectedCountyQuery.Split(new[]{ ',' });
foreach (var selectedCounty in selectedCountiesArray)
{
selectedCounties.Add(selectedCounty);
}
}
return selectedCounties;
You can get all parameter and value with Substring() and Split() method.
Example :
var URL = "controller/method?var1=&var2=&var3=dsgdf";
var ParameterPart = URL.Split("?")[1];
var ParametersArray = ParameterPart.Split("&");
//output : ["var1=","var2=","var3=dsgdf"];
foreach(var Parameter in ParametersArray)
{
var ParameterName= Parameter.Split("=")[0];
var ParameterValue= Parameter.Split("=")[1];
}
You can use a regex and extract the matches:
Regex r = new Regex(#"&(.+?)\+");
MatchCollection mc = r.Matches(s);
Then you can itterate your desired strings (in this case wow cities) like:
foreach(Match curMatch in mc)
{
Console.WriteLine(curMatch.Groups[1].Value);
}
string[] numbers ={ "/Gender=&Age=&Query=&Orgrimmar+l%C3%A4n=01&Stormwind+l%C3%A4n=07&Undercity+l%C3%A4n=09&Pag"};
string sPattern = #"(?<=&Orgrimmar)+";
foreach (string s in numbers){
if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern)){
System.Console.WriteLine(" - valid");}
else{System.Console.WriteLine(" - invalid");}
Output: valid
string[] numbers ={ "/Gender=&Age=&Query=Orgrimmar+l%C3%A4n=01&Stormwind+l%C3%A4n=07&Undercity+l%C3%A4n=09&Pag"};
Output: invalid
Further to check two parameters:
string[] numbers ={ "/Gender=&Age=&Query=&Orgrimmar+l%C3%A4n=01&Stormwind+l%C3%A4n=07&Undercity+l%C3%A4n=09&Pag"};
string sPattern = #"(?<=&Orgrimmar)+";
string sPattern2 = #"(?<=&Stormwind)+";
foreach (string s in numbers){
if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern) && System.Text.RegularExpressions.Regex.IsMatch(s, sPattern2))
...

How to Sort NameValue Collection and Store it in a string

Here I am storing two set of querystring parameters into two different namevalue collection. The querystring parameter order may vary so I just want to sort the order and then I need to store namevalue collection to a string.
Updated Code :
string url1 = #"http://www.somewebsitesampletest.com/dcs7o?data=142248494&dcp=smre&nparam=4567P&email=xxx.com";
string url2 = #"http://www.somewebsitesampletest.com/dcs7o?dcp=smre&data=142248494&email=xxx.com&nparam=4567P";
var NameValueCollection1 = HttpUtility.ParseQueryString(url1);
var NameValueCollection2 = HttpUtility.ParseQueryString(url2);
ExpectedResult:
After Sorting and converting to string the result should look like the below one
string query1 = "data=142248494&dcp=smre&email=xxx.com&nparam=4567P";
string query2 = "data=142248494&dcp=smre&email=xxx.com&nparam=4567P";
Here's a solution using Linq.
Basically it changes the NameValueCollection to an IEnumerable of the keys using Cast<T>, then the rest is fairly self explanatory.
public string GetSortedQueryString(string url)
{
var queryString = HttpUtility.ParseQueryString(url);
// Ignore null keys (caused by your ?& at the start of the query string
var orderedKeys = queryString.Cast<string>().Where(k => k != null).OrderBy(k => k);
return string.Join("&", orderedKeys.Select(k => string.Format("{0}={1}", k, queryString[k])));
}
Results for your URLs would be:
data=142248494&dcp=smre&email=xxx.com&nparam=4567P
data=142248494&dcp=smre&email=xxx.com&nparam=4567P
Email comes before nparam, unlike your expected solution (I'm assuming that was a mistake).
use LINQ with a Dictionary and a list of KeyValuePair :
string url1 = #"http://www.somewebsitesampletest.com/dcs7o?&data=142248494&dcp=smre&nparam=4567P&email=xxx.com";
string query1 ="";
Dictionary<String, String> paramDict = new Dictionary<string, string>();
var query = from match in urlString.Split('?').Where(m => m.Contains('='))
.SelectMany(pr => pr.Split('&'))
where match.Contains('=')
select new KeyValuePair<string, String>(
match.Split('=')[0],
match.Split('=')[1]);
query.ToList().ForEach(kvp => paramDict.Add(kvp.Key, kvp.Value));
var List<KeyValuePair<string, string>> paramList = paramDict.ToList();
paramList.Sort();
foreach (KeyValuePair<string, int> pair in list)
{
query1+=pair.Key+"="+pair.Value+"&";
}
query1=query1.TrimEnd('&');
I made this fiddle because I needed to sort querystring values in order to properly compare URIs: (H/T to Jacob's answer)
https://dotnetfiddle.net/eEhkNk
This preserves duplicate keys:
public static string[] QueryStringOmissions = new string[] { "b" };
public static NameValueCollection SortAndRemove(NameValueCollection collection)
{
var orderedKeys = collection.Cast<string>().Where(k => k != null).OrderBy(k => k);
var newCollection = HttpUtility.ParseQueryString(String.Empty);
foreach(var key in orderedKeys)
{
if (!QueryStringOmissions.Contains(key))
{
foreach(var val in collection.GetValues(key).Select(x => x).OrderBy(x => x).ToArray())
{
newCollection.Add(key, val);
}
}
}
return newCollection;
}

Extract data from a big string

First of all, i'm using the function below to read data from a pdf file.
public string ReadPdfFile(string fileName)
{
StringBuilder text = new StringBuilder();
if (File.Exists(fileName))
{
PdfReader pdfReader = new PdfReader(fileName);
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);
currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
text.Append(currentText);
pdfReader.Close();
}
}
return text.ToString();
}
As you can see , all data is saved in a string. The string looks like this:
label1: data1;
label2: data2;
label3: data3;
.............
labeln: datan;
My question: How can i get the data from string based on labels ?
I've tried this , but i'm getting stuck:
if ( string.Contains("label1"))
{
extracted_data1 = string.Substring(string.IndexOf(':') , string.IndexOf(';') - string.IndexOf(':') - 1);
}
if ( string.Contains("label2"))
{
extracted_data2 = string.Substring(string.IndexOf("label2") + string.IndexOf(':') , string.IndexOf(';') - string.IndexOf(':') - 1);
}
Have a look at the String.Split() function, it tokenises a string based on an array of characters supplied.
e.g.
string[] lines = text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
now loop through that array and split each one again
foreach(string line in lines) {
string[] pair = line.Split(new[] {':'});
string key = pair[0].Trim();
string val = pair[1].Trim();
....
}
Obviously check for empty lines, and use .Trim() where needed...
[EDIT]
Or alternatively as a nice Linq statement...
var result = from line in text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries)
let tokens = line.Split(new[] {':'})
select tokens;
Dictionary<string, string> =
result.ToDictionary (key => key[0].Trim(), value => value[1].Trim());
It's pretty hard-coded, but you could use something like this (with a little bit of trimming to your needs):
string input = "label1: data1;" // Example of your input
string data = input.Split(':')[1].Replace(";","").Trim();
You can do this by using Dictionary<string,string>,
Dictionary<string, string> dicLabelData = new Dictionary<string, string>();
List<string> listStrSplit = new List<string>();
listStrSplit = strBig.Split(';').ToList<string>();//strBig is big string which you want to parse
foreach (string strSplit in listStrSplit)
{
if (strSplit.Split(':').ToList<string>().Count > 1)
{
List<string> listLable = new List<string>();
listLable = strSplit.Split(':').ToList<string>();
dicLabelData.Add(listLable[0],listLable[1]);//Key=Label,Value=Data
}
}
dicLabelData contains data of all label....
i think you can use regex to solve this problem. Just split the string on the break line and use a regex to get the right number.
You can use a regex to do it:
Regex rx = new Regex("label([0-9]+): ([^;]*);");
var matches = rx.Matches("label1: a string; label2: another string; label100: a third string;");
foreach (Match match in matches) {
var id = match.Groups[1].ToString();
var data = match.Groups[2].ToString();
var idAsNumber = int.Parse(id);
// Here you use an array or a dictionary to save id/data
}

Categories

Resources