I have a list of two dimensions dynamic as follows :
List<dynamic> tableContent = new List<dynamic>();
List<dynamic> rowHeader = new List<dynamic>();
rowHeader.add("First header");
rowHeader.add("Second header");
rowHeader.add("Third header");
tableContent.add(rowHeader);
for (int i = 0; i < 5; i++) {
List<dynamic> rowContent = new List<dynamic>();
rowContent.add("1");
rowContent.add("2");
rowContent.add("3");
tableContent.add(rowContent);
}
My tableContent is essentially
"First header", "Second header", "Third header"
"1" , "2" , "3"
"1" , "2" , "3"
"1" , "2" , "3"
"1" , "2" , "3"
"1" , "2" , "3"
I want to transform it into json as
[{"First header":"1","Second header":"2","Third header":"3"}
, {"First header":"1","Second header":"2","Third header":"3"}
, {"First header":"1","Second header":"2","Third header":"3"}
, {"First header":"1","Second header":"2","Third header":"3"}
, {"First header":"1","Second header":"2","Third header":"3"}]
How do I do this without changing my initial for loop to create my tableContent? (since I also need it for doing something else).
Thank you
Eko
Your tableContent is not essential to your example. Your tableContent right now is a List<List<string>> so it will be serialized as
[["First header","Second header","Third header"],["1","2","3"],["1","2","3"],["1","2","3"],["1","2","3"],["1","2","3"]]
If you need to keep your for loop unchanged, then write your own custom serializer. If you have no need in keeping for loop unchanged, form your data in right way. For an example:
var tableContent = new List<dynamic>();
for (int i = 0; i < 5; i++)
{
var rowContent = new Dictionary<dynamic, dynamic>();
rowContent["First header"] = "1";
rowContent["Second header"] = "2";
rowContent["Third header"] = "3";
tableContent.Add(rowContent);
}
Will result as:
[{"First header":"1","Second header":"2","Third header":"3"},{"First header":"1","Second header":"2","Third header":"3"},{"First header":"1","Second header":"2","Third header":"3"},{"First header":"1","Second header":"2","Third header":"3"},{"First header":"1","Second header":"2","Third header":"3"}]
P.S. if you have no special purposes, you can change your dynamic to strong types:
var tableContent = new List<Dictionary<string, string>>();
for (int i = 0; i < 5; i++)
{
var rowContent = new Dictionary<string, string>();
rowContent["First header"] = "1";
rowContent["Second header"] = "2";
rowContent["Third header"] = "3";
tableContent.Add(rowContent);
}
You can use newtonsoft - Json.NET to build (and parse) jsons.
It can be used in various ways, both "manually" and using automatic serialization. See here: Creating JSON.
The code below demonstrates how to use the "manual" approach to build the json in parallel to building your current data structure (like I understood you'd like to do):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
namespace Test
{
internal class Program
{
static void Main(string[] args)
{
List<List<string>> tableContent = new List<List<string>>();
JArray tableJson = new JArray(); // This will be the table json object we will build
string[] headerNames = { "First header", "Second header", "Third header" };
List<string> rowHeader = new List<string>();
rowHeader.Add(headerNames[0]);
rowHeader.Add(headerNames[1]);
rowHeader.Add(headerNames[2]);
tableContent.Add(rowHeader);
for (int i = 0; i < 5; i++)
{
List<string> rowContent = new List<string>();
JObject rowJson = new JObject(); // This will be the json for one row
string[] rowElements = { "1", "2", "3" };
Debug.Assert(rowElements.Length == headerNames.Length);
for (int j = 0; j < rowElements.Length; ++j)
{
rowContent.Add(rowElements[j]);
rowJson[headerNames[j]] = rowElements[j]; // Add the element to the row json
}
tableContent.Add(rowContent);
tableJson.Add(rowJson); // Add the row json to the table json
}
// Here tableJson contains the required json.
// Convert to string and print:
string tableJsonString = tableJson.ToString();
Console.WriteLine(tableJsonString);
}
}
}
Output:
[
{
"First header": "1",
"Second header": "2",
"Third header": "3"
},
{
"First header": "1",
"Second header": "2",
"Third header": "3"
},
{
"First header": "1",
"Second header": "2",
"Third header": "3"
},
{
"First header": "1",
"Second header": "2",
"Third header": "3"
},
{
"First header": "1",
"Second header": "2",
"Third header": "3"
}
]
Note: I changed the dynamic lists to have concrete types as this is more efficient.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm making a program to automate rolling initiative. I have most of it done, but I can't sort the outputs because it's a jagged array. I need the second column of each array in my jagged array to be sorted from highest to lowest.
using System;
using System.Linq;
namespace Auto_Initiative
{
class Program
{
static void Main(string[] args)
{
string[] encounter =
{
"Wizard", "18", "-2",
"Bard", "9", "3",
"Goblin 1", "16", "1",
"Goblin 2", "14", "1"
};
int[][] numbers = new int[encounter.Length / 3][];
int loop = 0;
for(int i = 0; i > encounter.Length; i += 3)
{
// Name number, real roll
numbers[loop] = new int[2] {i, Int32.Parse(encounter[i + 1]) + Int32.Parse(encounter[i + 2])};
}
Console.ReadKey();
}
}
}
One part of designing your software is choosing the right data structure for how you are planning to use it. Sometimes redundant data is required but we don't know what you are requirements are to make that decision. So as was mentioned by Sergey you should consider creating a custom class which I have shown an example of below. Also note that a string[] is not really a jagged array. By definition a jagged array has nested arrays of variable size. The data structure depicted above could be put in a regular string[][] and would not be jagged.
Object Oriented in Action
What you are looking for is stored in unitsSortedBySecondColumn.
class so65865986
{
static void Main(string[] args)
{
Encounter encounter = new Encounter
{
Units = new List<EncounterUnit> {
new EncounterUnit{
Name = "Wizard",
Column1 = 18,
Column2 = -2,
},
new EncounterUnit{
Name = "Bard",
Column1 = 9,
Column2 = 3,
},
new EncounterUnit{
Name = "Goblin 1",
Column1 = 16,
Column2 = 1,
},
new EncounterUnit{
Name = "Goblin 2",
Column1 = 14,
Column2 = 1,
},
},
};
var unitsSortedBySecondColumn = encounter.Units
.OrderBy(u => u.Column1)
.Select(u => new int[] { u.Column1, u.Column2 })
.ToArray();
}
}
class EncounterUnit
{
public string Name;
public int Column1; //Change name to whatever it means
public int Column2; //Change name to whatever it means
}
class Encounter
{
public List<EncounterUnit> Units;
}
Nested (but not Jagged) Array
class so65865986_nested_array
{
static void Main(string[] args)
{
string[][] encounter =
{
new string[] {"Wizard", "18", "-2" },
new string[] {"Bard", "9", "3" },
new string[] {"Goblin 1", "16", "1" },
new string[] {"Goblin 2", "14", "1" },
};
int[][] numbers = encounter
.Select(u => new int[] { int.Parse(u[1]), int.Parse(u[2]) })
.OrderBy(u => u[0])
.ToArray();
Console.ReadKey();
}
}
Other Notes
Also, another note. You don't need to use Int32 because it is recommended you use the aliases provided which in this case is int.
use this code:
string[] encounter =
{
"Wizard", "18", "-2",
"Bard", "9", "3",
"Goblin 1", "16", "1",
"Goblin 2", "14", "1"
};
int[,] numbers = new int[encounter.Length / 3, 3];
for (int i = 1; i < encounter.Length / 4; i++)
{
for (int j = 0; j < encounter.Length / 3; j += 1)
{
numbers[j, i] = Convert.ToInt32(encounter[i + (j * 3)]);
Console.Write(numbers[j, i] + " ");
}
Console.WriteLine(Environment.NewLine);
}
Console.ReadLine();
I am creating an app that gets information and download movies from a site. I have succeeded in setting the information in different arrays and combining them together to 1 array.
However, now I am trying to put that array inside a bigger array (want to work with JSON), and that is failing.
My current Json output looks like this:
{"moviedata":
["http:/xxxx","title title ","k0X0HrYtMm5u"],"tags":
["x","x","x","Prop","x","x","x","x","x","x","x"],"categorydata":
["x","x","x"]}
Which is achieved with this code:
Dictionary<string, string[]> movie = new Dictionary<string, string[]>();
moviedata.Add("moviedata", moviegenerala);
moviedata.Add("tags", tagsa);
moviedata.Add("categorydata", categoriesa);
string moviejson = JsonConvert.SerializeObject(moviedata);
I want to add another layer on top of this, so there is a general tab named "Movie", and for each movie it has this information. How would I do that?
UPDATE:
Added this code:
var myShape = new
{
Movie = new Dictionary<string, string[]>
{
["moviedata"] = moviegenerala,
["tags"] = tagsa,
["categorydata"] = categoriesa,
["localdata"] = localdataa
}
};
var moviejson = JsonConvert.SerializeObject(myShape);
The JSON seems to be correct, but it cannot parse, after the first listing it says there is text after the closing bracket.
UPDATE:
Changed code to this:
Dictionary<string, string[]> movies = new Dictionary<string, string[]>();
var myShape = movies.Select(m => new
{
Movie = new Dictionary<string, string[]>
{
// TODO - you'll need to get the appropriate data for this movie
["moviedata"] = moviegenerala,
["tags"] = tagsa,
["categorydata"] = categoriesa,
["localdata"] = localdataa
}
});
var moviejson = JsonConvert.SerializeObject(myShape);
File.AppendAllText("moviedata.txt", moviejson);
But now it only gives empty brackets :(
If this is a one-off serialization, then simplest could be just to wrap the Dictionary with an anonymous class adding the extra property indentation, e.g.
var myShape = new
{
Movie = new Dictionary<string, string[]>
{
["moviedata"] = moviegenerala,
["tags"] = tagsa,
["categorydata"] = categoriesa
}
};
var moviejson = JsonConvert.SerializeObject(myShape);
However, if this same shape is required in multiple places in your code, then I would recommend that you create a fully fledged class for your 'Shape'.
Edit:
The json produced by the above is
{
"Movie": {
"moviedata": [ "http:/xxxx", "title title ", "k0X0HrYtMm5u" ],
"tags": [ "x", "x", "x", "Prop", "x", "x", "x", "x", "x", "x", "x" ],
"categorydata": [ "x", "x", "x" ]
}
}
If you need to map multiple Movies, then project then you can use a .Select:
// TODO : Replace this with your actual current movies
var inMovies = new[] {new Movie{...},new Movie {...}, ...};
var myShape = inMovies.Select(m => new
{
Movie = new Dictionary<string, string[]>
{
// TODO - you'll need to get the appropriate data for this movie, e.g. m.moviegenerala
["moviedata"] = moviegenerala,
...
}
});
Produces the following:
[
{
"Movie": {
"moviedata": [ "http:/xxxx", "title title ", "k0X0HrYtMm5u" ],
"tags": [ "x", "x", "x", "Prop", "x", "x", "x", "x", "x", "x", "x" ],
"categorydata": [ "x", "x", "x" ]
}
},
{
"Movie": {
"moviedata": [ "http:/xxxx", "title title ", "k0X0HrYtMm5u" ],
"tags": [ "x", "x", "x", "Prop", "x", "x", "x", "x", "x", "x", "x" ],
"categorydata": [ "x", "x", "x" ]
}
}
]
I have two lists of string:
List<string> tmpCols = new List<string>();
List<string> tmpRows = new List<string>();
e.g. tmpCols = [A,B,C]; and tmpRows = [X, Y];
I need to iterate both list and get a Json result like this:
new matrix() { id = "1", col = "A", row = "X" });
new matrix() { id = "2", col = "B", row = "X" });
new matrix() { id = "3", col = "C", row = "X" });
new matrix() { id = "4", col = "A", row = "Y" });
new matrix() { id = "5", col = "B", row = "Y" });
new matrix() { id = "6", col = "C", row = "Y" });
The dimension in this case would be 2 rows and 3 columns.
This is a textbook example of a nested loop. Loops can contain other loops, where the inner one repeats for each element of the outer one. This one might look something like:
var result = new List<matrix>();
var count = 1;
foreach (var r in tmpRows)
foreach (var c in tmpCols)
result.Add(new matrix { id = (count++).ToString(), col = c, row = r });
I think this is a late answer
need to iterate both list and get a Json result like this:
It is not a json, I guess you want something like this
List<string> tmpCols = new List<string>() { "A", "B", "C" };
List<string> tmpRows = new List<string>() { "X", "Y" };
var query = tmpCols.SelectMany(c => tmpRows.Select(r => new {id=index++, col=c, row = r }));
var json = JsonConvert.SerializeObject(query, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(json);
OUTPUT:
[
{
"id": 6,
"col": "A",
"row": "X"
},
{
"id": 7,
"col": "A",
"row": "Y"
},
{
"id": 8,
"col": "B",
"row": "X"
},
{
"id": 9,
"col": "B",
"row": "Y"
},
{
"id": 10,
"col": "C",
"row": "X"
},
{
"id": 11,
"col": "C",
"row": "Y"
}
]
Solved using this code:
var tmpMatrix = new List<matrix>();
for (int k = 0; k < tmpRows.Count; k++)
{
for (int j = 0; j < tmpCols.Count; j++)
{
int ident = k*tmpCols.Count + j;
tmpMatrix.Add(new matrix() { id = ident.ToString(), col = tmpCols[j], row = tmpRows[k] });
}
}
What is the best way to compare two lists based on values, order and the number of values. So all of the lists below should be different.
var list1 = new List<string> { "1", "2" };
var list2 = new List<string> { "2", "1" };
var list3 = new List<string> { "1", "2", "3" };
How about using SequenceEqual.
See http://ideone.com/yZeYRh
var a = new [] { "1", "2", "3" };
var b = new [] { "1", "2" };
var c = new [] { "2", "1" };
Console.WriteLine(a.SequenceEqual(b)); // false
Console.WriteLine(a.SequenceEqual(c)); // false
Console.WriteLine(c.SequenceEqual(b)); // false
It comes from the namespace System.Linq and can be used on any IEnumerable.
You can also pass it an IEqualityComparer to for example also do:
var d = new [] { "a", "B" };
var e = new [] { "A", "b" };
Console.WriteLine(d.SequenceEqual(e, StringComparer.OrdinalIgnoreCase)); // true
I like Zip for this, but you still need to manually compare Count.
lista.Count() ==listb.Count() && lista.Zip(listb, Equals).All(a=>a);
In my page i need to add 10,20,30,40,50 etc to dropdown.For that in my controller i added like this.
var resultsPerPage = new Collection<SelectListItem>(){
new SelectListItem { Text = "10", Value = "10" },
new SelectListItem { Text = "20", Value = "20" },
new SelectListItem { Text = "30", Value = "30" },
new SelectListItem { Text = "40", Value = "40" },
new SelectListItem { Text = "50", Value = "50" }};
But in code violation showing don't use multiple statements like that.can you give me any suggestion to avoid this lines of code.
following your pattern may be something like this may fit your needs:
var data = new List<int> {19, 29, 39, 49 ,50}; //COLLECTION OF ALL POSSIBLE VALUES
var resultsPerPage = new Collection<SelectListItem>(); //COLLECTION OF ITEMS
//INIT COLLECTION OF ITEMS
foreach(var v in data) {
resultsPerPage.Add(
new SelectListItem { Text = v .ToString(), Value = v .ToString() }
);
}