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 :)
Related
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;
}
}
}
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();
}
I have a key with random bits of string in it making it difficult to extract it's value. How would I go about doing it when I don't know the random bits ahead of time?
given:
sample = {\"total_ra4jhga987y3h_power\": 30}
Is it possible to do something directly like
dynamic obj = JsonConvert.DeserializeObject(sample);
obj[#"^total_(.*)_power$"] ---> should give me 30
Use LINQ to JSON instead. If you parse it as a JObject, you can iterate over all the properties, and find those which match your regex.
Regex regex = new Regex(...);
JObject json = JObject.Parse(text);
foreach (var property in json.Properties())
{
if (regex.IsMatch(property.Name))
{
...
}
}
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string,long>>(sample);
Regex rg = new Regex("total_.*_power");
var key = jsonDict.Keys.First(k=>rg.IsMatch(k));
Console.log(jsonDict[key]);
You can utilize LINQ to go through your properties and test their names for your regexp:
public static class JsonExtensions
{
public static Dictionary<string, JToken> PropertiesByRegexp(this JObject token, Regex regex)
{
return token.Properties()
.Where(p => regex.IsMatch(p.Name))
.ToDictionary(p => p.Name, p => p.Value);
}
}
You can now use this extensions method in the following way:
JObject sample = JsonConvert.DeserializeObject("{\"total_ra4jhga987y3h_power\": 30, \"not_matching\": 31}") as JObject;
var result = sample.PropertiesByRegexp(new Regex("^total_(.*)_power$"));
foreach (var propertyPair in result)
{
Console.WriteLine($"{propertyPair.Key}: {propertyPair.Value}");
}
Outputs:
total_ra4jhga987y3h_power: 30
I am trying to do a simple replace. My problem is that instead of replacing the string, it appears it grabs the last couple characters and appends them to the end.
public static Dictionary<string, string> dict = new Dictionary<string, string> {
{"1", #"\\id 1ch\n fjdsbfjdshfd"},
{"2", #"\\id 1co\n fjdsbfjdshfd"},
{"3", #"\\id 1th\n fjdsbfjdshfd"}
};
public static string bookNameFn(string line)
{
return line.Split(' ')[1].ToLower().Replace("1ch", "1Chr").Replace("1co", "1Cor").Replace("1th", "1Thess");
}
foreach (KeyValuePair<String, String> usfm in dict)
{
foreach (var line in usfm.Value.Split('\n'))
{
if (line.StartsWith("\\id "))
{
Console.WriteLine(bookNameFn(line));
}
}
}
output
1Chrr
1Corr
1Thessess
desired output
1Chr
1Cor
1Thess
Use literal notation e.g.
#"\id 1th\n fjdsbfjdshfd";
It will work, the problem is the way the value is interpreted through the string constructor.
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.