Can we convert the style attribute value into a dictionary in C# - 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;
}
}
}

Related

Extract key value pair from dictionary

I'm at the first step in programming and i'm stuck with a problem with Dictionary(key value) pair.
The statement of the problem is:
Write a console application that extracts and prints the key and value on a line.
Example:
For input data:
year:2018
The console will display:
year
2018
here is my code:
string inputData = Console.ReadLine();
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add(inputData, 2018 );
foreach (KeyValuePair<string, int> kvp in dictionary)
{
Console.WriteLine("{0}\n{1}", kvp.Key, kvp.Value);
}
// expects year:2018
var inputData = Console.ReadLine();
// split by ':' to get 'year' and '2018' values
var values = inputData.Split(':');
// creates a dictionary
var dictionary = new Dictionary<string, int>();
// add the 'year' string as key and '2018' as value
dictionary.Add(values[0], Convert.ToInt32(values[1]));
// print all the dictionary
foreach (var kvp in dictionary)
{
Console.WriteLine("{0}\n{1}", kvp.Key, kvp.Value);
}
However, the problem description is not asking you to use a dictionary.
So, instead of creating a dictionary, you can simply print the values.
var inputData = Console.ReadLine();
var values = inputData.Split(':');
Console.WriteLine(values[0]);
Console.WriteLine(values[1]);

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

String parsing (splitting and retrieving parameters)

I have a string formatted this way:
<?TAG param1="val1" parm2="val2" paramN="valN" /><?TAG param1="val1" parm2="val2" paramN="valN"/><?TAG param1="val1" parm2="val2" paramN="valN"/>
"TAG" is always the same value, but number of occurrences is variable and the number of parameters for each occurrence too. I can't change the source format.
I need to get the list of parameters for each occurrence using C# (.NET 4.0) Can you help me out?
XElement rootElement = XElement.Parse(string.Format("<element>{0}</element>",
yourString.Replace("?TAG", "TAG")));
var elements = rootElement.Elements();
var yourResult = elements.Select(x => new TagsAndParams { Tag = x,
Params = x.Attributes.Where(xa => xa.Name.LocalName.BeginsWith("param") });
With this class as a result holder (I know I could use anonymous types, but this is better for passing to other functions):
public class TagsAndParams
{
XElement Tag;
IEnumerable<XAttribute> Params;
}
You could do it with a nasty looking RegEx, but I'd make sure it's not actually an XML PI chain first:
(?<tag><?TAG (?<parm>param\d{1,2}=\"[^\"]+\"\s*)*\/\>)*
This will match groups, each group containing:
full tag
paramX="valX" pair
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
class ExampleClass
{
static void Main(string[] args)
{
string example = "<?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\" /><?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\"/><?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\"/>";
List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
string[] tokens = Regex.Split(example, "/><\\?TAG|<\\?TAG|/>");
foreach (string token in tokens) if (token.Length > 0)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
string[] parms = token.Split(' ');
foreach (string parm in parms) if (parm.Length > 0)
{
string[] keyvalue = Regex.Split(parm, "=\"|\"");
parameters.Add(keyvalue[0], keyvalue[1]);
}
result.Add(parameters);
}
Console.WriteLine("TAGs detected: " + result.Count);
foreach (Dictionary<string, string> token in result)
{
Console.WriteLine("TAG");
foreach (KeyValuePair<string, string> kvp in token)
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
}
}
I've finally solved using this code (provided by a friend of mine). The trick was the Regex used for splitting individual elements. Thank you for the support, I will make use of the tip about xml parser in future :)

Sorting a SortedDictionary of <String,int> Alphabetically, reverse Alphabetically, and the value's frequency

I'm brand new to C# and the concept of hash tables/dictionary's and have been searching for a straight answer on this for quite awhile, but I can not find any solutions that actually works (likely due to my ignorance of the subject) so I need a solution in simple terms if possible.
Also, if it makes a difference, the Strings and ints in the dictionary are not data members or even parameters.
More Description:
The program overall, is to import words via text file or direct user input then save them and the number of times they appear (AKA store in Dictionary/Sorteddictionary) then allow users to reorganize the data, alphabetically, reverse alphabetically, or by frequency and/OR print them to the console or write the data to a new .txt file.
However right now I am only trying to get the sorting of the dictionary to work.
Example input:
Another great story and another great adventure.
Example Output(alphabetically):
Words Starting with letter A:
another adventure and
Letter Starting with letter G:
great
(Ect.)
Example Output(reverse alphabetically):
Words Starting with letter S:
story
Words Starting with letter G:
great
(ect.)
Output(frequency):
number of words occurring 2 time(s):
another great
number of words occurring 1 time(s):
and adventure story.
Hope this helps. I'm not sure it's the best way to approach your problem, but it should help you to familiarise yourself with some of the options / see why some of the guys on here are advising against it. If you let us know more about what you're trying to do we can better advise alternate approaches.
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackOverflow.Demos
{
class Program
{
const string OutputFormat = "{0}: {1}";
public static void Main(string[] args)
{
new Program();
Console.WriteLine("Done");
Console.ReadKey();
}
public Program()
{
SortedDictionary<string, int> dic = new SortedDictionary<string, int>();
dic.Add("a", 1);
dic.Add("b", 2);
dic.Add("d", 2);
dic.Add("c", 1);
dic.Add("e", 1);
dic.Add("f", 3);
dic.Add("g", 4);
dic.Add("h", 2);
dic.Add("i", 2);
OutputByKeyAsc(dic);
OutputByKeyDesc(dic);
OutputByValueFrequency(dic);
}
void OutputByKeyAsc(SortedDictionary<string, int> dic)
{
Console.WriteLine("OutputByKeyAsc");
foreach (string key in dic.Keys)
{
Console.WriteLine(string.Format(OutputFormat, key, dic[key]));
}
}
void OutputByKeyDesc(SortedDictionary<string, int> dic)
{
Console.WriteLine("OutputByKeyDesc");
foreach (string key in dic.Keys.Reverse())
{
Console.WriteLine(string.Format(OutputFormat, key, dic[key]));
}
}
void OutputByValueFrequency(SortedDictionary<string, int> dic)
{
Console.WriteLine("OutputByValueFrequency");
IEnumerable<KeyValuePair<int,int>> values =
(
from sortedItem
in
(
from entry
in dic
group entry
by entry.Value
into result
select new KeyValuePair<int,int>(result.Key , result.Count())
)
orderby sortedItem.Value descending
select sortedItem
).ToArray();
foreach (KeyValuePair<int, int> value in values)
{
foreach (KeyValuePair<string, int> item in dic.Where<KeyValuePair<string, int>>(item => item.Value == value.Key))
{
Console.WriteLine(string.Format(OutputFormat, item.Key, string.Format(OutputFormat, item.Value, value.Value)));
}
}
}
}
}
Good luck / hope you're enjoying c# so far.
EDIT
Based on the new info in your question here's my attempt at a neater solution:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace StackOverflow.Demos
{
class Program
{
const string OutputFormat = "{0}: {1}";
public static void Main(string[] args)
{
new Program("Another great story and another great adventure.");
Console.WriteLine("Done");
Console.ReadKey();
}
public Program(string userInput)
{
//break string into words
IEnumerable<IGrouping<string, int>> words = Regex.Split(userInput, #"\W+").GroupBy(word => word.ToLowerInvariant(), word => 1); //nb converting word to lower case to avoid case sensitive comparisons in grouping - I can keep the original value(s) by replacing "word => 1" with "word => word" if needed
Console.WriteLine("\nWords in alphabetic order");
foreach (IGrouping<string, int> wordInfo in words.OrderBy(word => word.Key))
{
Console.WriteLine(string.Format(OutputFormat, wordInfo.Key,wordInfo.Count()));
}
Console.WriteLine("\nWords in descending alphabetic order");
foreach (IGrouping<string, int> wordInfo in words.OrderByDescending(word => word.Key))
{
Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Count()));
}
Console.WriteLine("\nWords by frequency (desc)");
foreach (IGrouping<string, int> wordInfo in words.OrderByDescending(word => word.Count()))
{
Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Count()));
}
}
}
}
EDIT
Here's the same code with the functionality in a class and the output kept in the program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace StackOverflow.Demos
{
class Program
{
const string OutputFormat = "{0}: {1}";
public static void Main(string[] args)
{
new Program("Another great story and another great adventure.");
Console.WriteLine("Done");
Console.ReadKey();
}
public Program(string userInput)
{
WordCounter myWordCounter = new WordCounter(userInput);
Console.WriteLine("\n**Alphabetical**");
foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByWordAlphabeticalDesc())
{
Console.WriteLine(string.Format(OutputFormat,wordInfo.Key, wordInfo.Value));
}
Console.WriteLine("\n**Alphabetical Desc**");
foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByWordAlphabeticalDesc())
{
Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Value));
}
Console.WriteLine("\n**Frequency Desc**");
foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByFrequency())
{
Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Value));
}
}
}
public class WordCounter
{
string sentance;
IEnumerable<IGrouping<string, int>> words;
public WordCounter(string sentance)
{
this.sentance = sentance;
GetWords();
}
void GetWords()
{
this.words = Regex.Split(this.sentance, #"\W+").GroupBy(word => word.ToLowerInvariant(), word => 1);
}
public IEnumerable<KeyValuePair<string, int>> GetWordCountByWordAlphabetical()
{
return this.words.OrderBy(word => word.Key).Select(wordInfo => new KeyValuePair<string,int>(wordInfo.Key, wordInfo.Count()));
}
public IEnumerable<KeyValuePair<string, int>> GetWordCountByWordAlphabeticalDesc()
{
return this.words.OrderByDescending(word => word.Key).Select(wordInfo => new KeyValuePair<string, int>(wordInfo.Key, wordInfo.Count()));
}
public IEnumerable<KeyValuePair<string, int>> GetWordCountByFrequency()
{
return this.words.OrderByDescending(word => word.Count()).Select(wordInfo => new KeyValuePair<string, int>(wordInfo.Key, wordInfo.Count()));
}
}
}
Since you aren't always displaying the data in a single consistently sorted manor I don't see any compelling reason to store the data in a sorted manor. You're likely better off just storing the data however you want, and then sorting it whenever the user requests to see it in some particularly sorted manor.

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.

Categories