If need an simple way to parse this string:
string a = "[[[
[-118.407, 33.749],
[-118.407, 33.749],
[-118.407, 33.749],
[-118.407, 33.749],
[-118.407,33.749]
]]]"
to something like: List<List<List<List<double>>>>
you can use your code fragments diectly with the right method:
var r = System.Text.Json.JsonSerializer.Deserialize< List<List<List<List<double>>>> >(a);
System.Text.Json is the new .net Core serializer, for older platforms use Newtonsoft:
var r = Newtonsoft.Json.JsonConvert.DeserializeObject< List<List<List<List<double>>>> >(a);
But I think you may have 1 level of List<> too many. Experiment.
Related
I'm very confused about the Unity JsonUtility, mainly due to lack of c# understanding.
All their examples are with very non generic classes, but I need flexibility, and havent been able to find a good e2e example that worked for me.
I have this simple json data that I need to work with:
"{
1: 987,
2: 123,
3: 001,
4: 157,
}"
It's a key value object where both key and value are integers.
My problem is that the size of the object is unknow, the index could be ever increasing, and I do not understand how I can define a generic object (class?) in c# that JsonUtility can convert. Do I need to define a class, or can I do it inline? Do I need to define getters and setter, or are there some convenient wildcard dictionary like thingy that would be suitable?
I'm trying to achieve something like this:
string jsonString = "{1:987,2:123,3:001,4:157}":
var object = JsonUtility.FromJson<??????>(jsonString);
Debug.Log(object[1]) // 987
Debug.Log(object[99]) // undefined
And then I would like to be able to add new pair to the object and at last turn it into json again something like:
object[100] = 999;
const jsonString = JsonUtility.ToJson<??????>(object);
Debug.Log(jsonString) // "{1:987,2:123,3:001,4:157,100:999}":
KeyValuePairs or Dictionary is not supported by the built-in JsonUtility.
You can use Newtonsoft .Net JSON (there is a wrapper Package for Unity) where this would be a simple Dictionary<int, int>
var json = "{1:987,2:123,3:001,4:157}":
var values = JsonConvert.DeserializeObject<Dictionary<int, int>>(json);
Debug.Log(values [2]);
and
var values = new Dictionary<int, int>{ { 2, 123 }, {7, 345} };
var json = JsonConvert.SerializeObject(values);
Debug.Log(json);
Coming from Python, I could easily do array[0][0], but doesn't seem like it in C#.
When I try to fetch data from my MySQL database, it gives me a 2D array, hence the need to use a 2D array.
Array looks like this:
[[hello], [world]]
I'd like to just fetch the string "hello". How would I manage that?
You use
string value = array[0,0];
Here:
var array= new String[,] {{"Hello","World"}};
string value=array[0,0];
You can access multidimensional arrays like this:
int val = a[2,3];
The above statement takes 4th element from the 3rd row of the array.
In your case it would be:
string val = a[0,0];
Pretty straightforward: arrray[0, 0]
Reference
carry the code below where I embarked.
class readFile{
List<double> out1 = new List<double>();
List<double> out2 = new List<double>();
List<double> out3 = new List<double>();
public readFile()
{
}
public void aproCSV()
{
var reader = new StreamReader(File.OpenRead(#"C:\altraprova.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
out1.Add(values[0]);
out2.Add(values[1]);
out3.Add(values[2]);
}
}
}
Allow me to explain my intent ....
I open my csv file
the goal is to read the second column and insert it into a list of type double and then get the value MAX.
If you use lists of type string not get erors .... but since the values contain only numbers you are signed semicolon, then I need to use the type double.. using the double type get the following error:
error 5 The best match of the overloaded method for
'System.Collections.Generic.List <double> .Add (double)' has some
invalid arguments
Split() returns a string[] and your lists are of type List<double> which means you need to parse the strings into doubles like the following:
double value1 = double.Parse(values[0]); etc
then add them to your list: out1.Add(value1);
Do be aware that you have no error handling so if the value is not a double, the code will still throw an exception.
CSV are surprisingly not so straightforward to parse, there are a lot of special cases which you have to take into consideration. For example, if your data would contain the "separation character" you'd need to put the data between quotes ("). If he contains quotes, then you have to escape them with a backslash (\) (or doubling them, I'm not sure).
So, except if you know the data you're going to be importing and are sure that those case won't happen, a simple "split" won't be sufficient.
I really recommend using an existing parser to help you on this task. I've used CsvHelper with success. It's a nice library and quite easy to use.
You need to do some parsing, because a generic list only accepts elements of the given type (double in your case):
var line = reader.ReadLine();
var values = line.Split(';');
out1.Add(double.Parse(values[0]));
out2.Add(double.Parse(values[1]));
out3.Add(double.Parse(values[2]));
This is the quick and dirty trick, you should use double.TryParse
for safety because maybe not everything you get is a double.
From you code I suppose the you need to get the max from list out2 (your second column). For this, use List.Max Method
When creating webservices, in c#, I have found it very useful to pass back jagged arrays, i.e. string[][]
I also found a neat trick to build these in a simple way in my code, which was to create a List and convert it by doing a ToArray() call.
e.g.
public string[][] myws() {
List<string[]> output = new List<string[]>();
return output.ToArray();
}
I would like to be able to employ a similar solution, but I can't think how to do something similar with a 3 level jagged array or string[][][], without resorting to loops and such.
Regards
Martin
You can get there by doing a Select() which converts each inner List<string> to an array using ToArray(), and then converting those results using ToArray():
var x = new List<List<string[]>>();
string[][][] y = x.Select(a => a.ToArray()).ToArray();
And so on for as many levels deep as you'd want to go.
My project requires a file where I will store key/value pair data that should be able to be read and modified by the user. I want the program to just expect the keys to be there, and I want to parse them from the file as quickly as possible.
I could store them in XML, but XML is way to complex, and it would require traversing nodes, and child nodes and so on, all I want is some class that takes a file and generates key value pairs. I want as little error handling as possible, and I want it done with as little code as possible.
I could code a class like that myself, but I'd rather learn how it's don'e in the framework than inventing the wheel twice. Are there some built in magic class in .NET (3.5) that are able to do so?
MagicClass kv = new MagicClass("Settings.ini"); // It doesn't neccesarily have to be an INI file, it can be any simple key/value pair format.
string Value1 = kv.get("Key1");
...
If you're looking for a quick easy function and don't want to use .Net app\user config setting files or worry about serialization issues that sometimes occur of time.
The following static function can load a file formatted like KEY=VALUE.
public static Dictionary<string, string> LoadConfig(string settingfile)
{
var dic = new Dictionary<string, string>();
if (File.Exists(settingfile))
{
var settingdata = File.ReadAllLines(settingfile);
for (var i = 0; i < settingdata.Length; i++)
{
var setting = settingdata[i];
var sidx = setting.IndexOf("=");
if (sidx >= 0)
{
var skey = setting.Substring(0, sidx);
var svalue = setting.Substring(sidx+1);
if (!dic.ContainsKey(skey))
{
dic.Add(skey, svalue);
}
}
}
}
return dic;
}
Note: I'm using a Dictionary so keys must be unique, which is usually that case with setting.
USAGE:
var settingfile = AssemblyDirectory + "\\mycustom.setting";
var settingdata = LoadConfig(settingfile);
if (settingdata.ContainsKey("lastrundate"))
{
DateTime lout;
string svalue;
if (settingdata.TryGetValue("lastrundate", out svalue))
{
DateTime.TryParse(svalue, out lout);
lastrun = lout;
}
}
Use the KeyValuePair class for you Key and Value, then just serialize a List to disk with an XMLSerializer.
That would be the simplest approach I feel. You wouldn't have to worry about traversing nodes. Calling the Deserialize function will do that for you. The user could edit the values in the file if they wish also.
I don't know of any builtin class to parse ini file. I've used nini when needed to do so. It's licensed under the MIT/X11 license, so doesn't have any issue to be included in a closed source program.
It's very to use. So if you have a Settings.ini file formatted this way:
[Configuration]
Name = Jb Evain
Phone = +330101010101
Using it would be as simple as:
var source = new IniConfigSource ("Settings.ini");
var config = source.Configs ["Configuration"];
string name = config.Get ("Name");
string phone = config.Get ("Phone");
if you want the user to be able to read and modify the file, i suggest a comma-delimited pair, one per line
key1,value1
key2,value2
...
parsing is simple: read the file, split at newline or comma, then take the elements in pairs
Format the file this way:
key1=value1
key2=value2
Read the entire file into a string (there is a simple convenience function that does that, maybe in the File or string class), and call string.Split('='). Make sure you also call string.Trim() on each key and value as you traverse the list and pop each pair into a hashtable or dictionary.