how to intersect multiple Maps (dictionary) in Dart - json

I have a List consisting of multiple Maps (Dictionaries) regardless of the value of each element in the map
var list = [{'a':1, 'b':1, 'c':7},
{'J':8, 'b':2, 'e':2},
{'l':1, 'b':3, 'r':4},
{'u':9, 'k':7} ];
Note that I don't know how many maps the list will have. It could be 0 and could be 1000 (I read from a JSON file).
I want to intersect them so the output would be like this:
var res = 'b';
I've done it in python by using this method:
res = set.intersection(*map(set, list))

The following would do the trick. It folds the list by intersecting the map keys one by one.
final list = [
{'a': 1, 'b': 1, 'c': 7},
{'J': 8, 'b': 2, 'e': 2},
{'l': 1, 'b': 3, 'r': 4},
{'u': 9, 'b': 7}
];
final res = list.fold<Set<String>>(
list.first.keys.toSet(),
(result, map) => result.intersection(map.keys.toSet()),
);
print(res); // Prints: {b}

Related

Convert Unquoted JSON Using Dart

I am getting unquoted JSON from a trusted 3rd party that looks like this:
{id: 2, name: Test Testerson, course_progress: 0, last_activity_date: null}, {id: 3, name: Poghos Adamyan, course_progress: 0, last_activity_date: null}
What is the best way using Dart for me to format this into valid JSON for use?
If you're absolutely certain that your response is that verbatim string and that you haven't already decoded it, then you would have to parse it manually and hope that there will never be ambiguity. If the data always follows a strict format and if all fields are always in a specific order, you could write a regular expression to parse it. For example:
void main() {
var s =
'{id: 2, name: Test Testerson, course_progress: 0, last_activity_date: null}, {id: 3, name: Poghos Adamyan, course_progress: 0, last_activity_date: null}';
var re = RegExp(
r'\{'
r'id: (?<id>\d+), '
r'name: (?<name>[^,]+), '
r'course_progress: (?<progress>\d+), '
r'last_activity_date: (?<last>[^}]+)'
r'\}',
);
var matches = re.allMatches(s);
var items = <Map<String, dynamic>>[
for (var match in matches)
<String, dynamic>{
'id': int.parse(match.namedGroup('id')!),
'name': match.namedGroup('name')!,
'course_progress': int.parse(match.namedGroup('progress')!),
'last_activity': DateTime.tryParse(match.namedGroup('last')!),
}
];
items.forEach(print);
}

How does the Iterable.expand(Iterable Function(dynamic) f) function works in Dart?

As per the example from the documentation:
var pairs = [[1, 2], [3, 4]];
var flattened = pairs.expand((pair) => pair).toList();
print(flattened); // => [1, 2, 3, 4];
var input = [1, 2, 3];
var duplicated = input.expand((i) => [i, i]).toList();
print(duplicated); // => [1, 1, 2, 2, 3, 3]
It looks like it flattens an iterable if it contains nested iterables, but how is the question.
What it basically does is that, it iterates over the iterable calling the argument function on each iteration and concatenating the iterables returned by the argument function once the iteration is over and lastly returning the result of the concatenation which is an iterable.
That was a summary on how it works, let's understand it using the example from the documentation itself:
var pairs = [[1, 2], [3, 4]];
var flattened = pairs.expand((pair) => pair).toList();
print(flattened); // => [1, 2, 3, 4];
Here we have an iterable pairs and we called the expand() method on it. Now the expand() method will iterate over pairs calling the argument function which is (pair) => pair once per iteration.
Note that the syntax of the expand() method look like this Iterable<T> expand<T>(Iterable<T> f(T element)) which clearly shows that it takes a function as an argument which takes an argument of type T and returns an iterable. e.g.(pair) => pair where the pair is of type List<int>
As of now we are clear that the expand() method iterates over an iterable calling the argument function on each iteration. The argument function takes an argument which is of same type as the iterable and it returns an iterable.
Lastly, the expand() method concatenates the iterables returned by the argument function once the iteration on the iterable e.g. pairs is over [1, 2] + [3, 4] = [1, 2, 3, 4]. Then it returns the result of the concatenation which is an iterable [1, 2, 3, 4].
It's basically just a loop within a loop that iterates into each iterable, finds each inner element of the inner iterable, then returns it as a single stretched out iterable.
I can't find source code for expand, but in my darq package, you can see the same concept in action using the selectMany method (which is because selectMany is just expand with an additional index passed to the selector). For how Dart's expand works, ignore all the parts that deal with index.
extension SelectManyExtension<T> on Iterable<T> {
/// Maps elements in an iterable to collections and then flattens those
/// collections into a single iterable.
///
/// During iteration, the [selector] function is provided each value in the iterable
/// along with the index of the value in the iteration. The
/// returned collection of that function is then iterated over, and each
/// value in that iteration is provided as the next element of the
/// resulting iterable. The result is all of the collections flattened so that
/// their values become elements in a single iterable.
///
/// Example:
///
/// void main() {
/// final list = ['abc', 'de', 'f', 'ghij'];
/// final result = list.selectMany((s, i) => s.iterable);
///
/// // Result: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
/// }
Iterable<TResult> selectMany<TResult>(
Iterable<TResult> Function(T element, int index) selector) sync* {
var index = 0;
for (var v in this) {
yield* selector(v, index++);
}
}
}
var list = [[1, 2, 3], [4, 5], [6]];
var flattened = list.selectMany((inner, idx) => inner);
// flattened = [1, 2, 3, 4, 5, 6]

Convert results from query to json object

I am attempting to convert an api from PHP to react.js. my data looks like this:
s
c
d
A
1
4/1
B
4
4/1
A
2
4/2
B
5
4/2
A
3
4/3
B
6
4/3
I pass json back to the app and it's built like this in PHP.
$graph_arr['bar']['series'][$s] += (int) $c;
$graph_arr['line']['series'][$s][] = (int) $c;
the resulting json looks like this
{line:
{labels: ['4/1','4/2','4/3'], //already have this figured out
series: [{ name: 'A', data: [1,2,3]},
{ name: 'B', data: [4,5,6]}
]}
}
How would I do this in react, new to react.js so I am not too familiar everything works or is constructed yet.
const graph_data = [['a',1,'4/1'],['a',2,'4/1'],['a',3,'4/1'],
['a',4,'4/4'],['b',5,'4/1'],['b',6,'4/1'],['b',7,'4/1'],['b',8,'4/4']]
const series = Object.entries(graph_data).map((row,i) => { })
edit:
found this How to group an array of objects by key. which is close
You can treat it just like you do an array in PHP.
jsonData["line"]["series"][0].name
You can also extract (deconstruct) the data out
const jsonData = {
line: {
labels: ["4/1", "4/2", "4/3"], //already have this figured out
series: [
{ name: "A", data: [1, 2, 3] },
{ name: "B", data: [4, 5, 6] }
]
}
};
const { line } = jsonData;
const { labels, series } = line;
{labels}
{labels[0]}
{series.map((data) => data.name)}
I put them in an example with a couple of different ways for you:
https://codesandbox.io/s/determined-keller-3ott6?file=/src/App.js

How to ignore object field in Angular7

How can I tell Angular to ignore one or more fields before the http call; like the #JsonIgnore in java.
Example:
I have this object: {id: 1, libelle: 'test', mustIgnore: 'test'};
I expect this object to be : {id: 1, libelle: 'test'};
I tried delete object.field, but I'm looking for a simpler way to do it, like using an annotation on my object.
Because if I have an array of objects, it becomes more difficult to manage it.
EDIT :
I do not want to do this manually for every object! Is there a way to just specify the fields that I want to delete and do it automatically, whenever I have a different object with different fields to delete
Use ES6 object destructuring to get an immutable object without the desired property.
const obj = {id: 1, libelle: 'test', mustIgnore: 'test'};
// Destructure into mustIgnore and rest properties
const { mustIgnore, ...rest } = obj;
const projectedObject = rest;
console.log("old", obj);
console.log("new", projectedObject);
If you have an array, you can simply map like:
const ignoreArray = array
.map(
a => ({ id: a.id, libelle: a.libelle })
)
As a result you have an array of objects with only id and libelle.
EDIT:
Based on Kunal answer, a better approach would be:
const ignoreArray = array
.map(
obj => {
const { mustIgnore1, mustIgnore2, ...rest } = obj;
return rest
}
)
Where mustIgnore1,mustIgnore2, etc. They would be the fields to eliminate
If your data set only contains key+value combinations, you can create a new empty object {} and loop through all the members of your original object with a for loop and check for each key with an array of key names you want to ignore. If the item is in the array, skip it, if it is not you add it to your new object.
const array = [
{id: 1, libelle: 'test1', mustIgnore: 'ignore1'},
{id: 2, libelle: 'test2', mustIgnore: 'ignore2'},
{id: 3, libelle: 'test3', mustIgnore: 'ignore3'}
];
const newArray = [];
for (element of array) {
const { mustIgnore, ...rest } = element;
newArray.push(rest);
}
console.log(newArray);
Another way:
const array = [
{id: 1, libelle: 'test1', mustIgnore: 'ignore1'},
{id: 2, libelle: 'test2', mustIgnore: 'ignore2'},
{id: 3, libelle: 'test3', mustIgnore: 'ignore3'}
];
const newArray = array.map(obj => {
const { mustIgnore, ...rest } = obj;
return rest;
});
console.log(newArray);
Please look object destructuring for further reference, but this is pretty much it!

Need to produce JSON in specific format

I have such JSON array in file
var jsonfromfile = [
[Date.UTC(2004, 1, 3), 19.3],
[Date.UTC(2004, 1, 10), 12.7],
[Date.UTC(2004, 1, 17), 3.6],
[Date.UTC(2004, 1, 24), 19.1],
[Date.UTC(2004, 1, 31), 12.1],
[Date.UTC(2004, 2, 7), 11.3],
[Date.UTC(2004, 2, 28), 9.3],
[Date.UTC(2004, 3, 6), 14.3],
[Date.UTC(2004, 3, 13), 5.8],
[Date.UTC(2004, 3, 20), 8.6],
[Date.UTC(2004, 3, 27), 19.9],
[Date.UTC(2004, 4, 3), 14.2],
[Date.UTC(2004, 4, 10), 12.8],
[Date.UTC(2004, 4, 17), 10.6],
[Date.UTC(2004, 4, 24), 8.4],
[Date.UTC(2004, 5, 1), 19.8],
[Date.UTC(2004, 5, 8), 13.8]
];
Which i was using as dummy data making first steps with this charts http://www.highcharts.com/products/highstock.
Now i want to use dynamic data with that charts, so i have controller which returning Key-Value data
public virtual JsonResult GetData(int type)
{
Dictionary<string, decimal> data = getData(type);
return Json(data.ToArray(), JsonRequestBehavior.AllowGet);
}
and i calling that controller with jquery ajax.
var jsonFirstTry = {
data: []
};
$.ajax({
url: actionUrl,
dataType: 'json',
cache: false,
data: { type: type },
success: function (items) {
var jsonSecondTry = "[";
$.each(items, function (itemNo, item) {
jsonFirstTry.data.push(item.Key, item.Value);
jsonSecondTry += "[" + item.Key + "," + item.Value + "],";
})
jsonSecondTry = jsonSecondTry.substring(0, jsonSecondTry.length-1);
jsonSecondTry += "];";
//...
}
});
I was trying reproduce the data like in js file (jsonfromfile) jsonFirstTry and jsonSecondTry but couldn't do the data exactly like in js file
Here is how the data loaded from js file looking in debug like that:
Here is how data looking from my first try
Here is second try data(but it is just string so it is not valid data for chart....)
So i need to generate the same jason like in first image, any thoughts how can i do that?
Your initial example ( var jsonfromfile = [... ) is not JSON. It is an array of arrays (in JavaScript), using JavaScript's array literal syntax.
JSON is a string representing a serialized data structure, using a subset of the JavaScript object literal syntax. JSON cannot have method calls or method definitions.
Thus, attempting to provide, in JSON format, what you used as sample data will not work. You need to provide real JSON and manipulate it as needed (calling Date.UTC() on portions of it) when received.