Flutter convert a list of maps into a single map - flutter

I have a list of maps in flutter with each map having only 2 keys. I would like convert them into a single map where the first key is a key and the second key becomes the value.
This is the list of maps
List results = [[
{ key: shortcuts_cart_createCart, value: 0 },
{ key: shortcuts_cart_discountCartTotal, value: 0 },
{ key: shortcuts_selling_cart, value: 0 },
]
I would like to convert the list to this map
Map shorts = {
shortcuts_selling_cart : 0,
shortcuts_cart_createCart : 0,
shortcuts_cart_discountCartTotal : 0
}
How do I achieve that

you can try this
List results = [
{ "key": "shortcuts_cart_createCart", "value": 0 },
{ "key": "shortcuts_cart_discountCartTotal", "value": 0 },
{ "key": "shortcuts_selling_cart", "value": 0 },
];
var map={};
results.forEach((element){
map[element["key"]]=element["value"];
});
print(map);

You can use Map.fromIterable and do it by one line:
var result = Map.fromIterable(l, key: (v) => v[0], value: (v) => v[1]);
but romIterable has very weak typing. So collection-for is the only recommended way which is:
var result = { for (var v in l) v[0]: v[1] };

I'd use MapEntry.
Map.fromEntries(results.map(
(innerMap) => MapEntry(innerMap['key'], innerMap['value']),
));
Also note that your code is not syntactically valid. In Dart, you have to always quote strings, even if they are keys in a map, check the documentation.

Related

Search Key in Nested json in Dart/Flutter

I want to search the key "AylaHeartBeatFrequency" inside nested json. how to search and get its value ? in flutter/dart
{
"sAWSIoT": {
"CloudStatus": 1,
"PairingFlag": 0,
},
"sDebug": {
"LocalDebugMsg_d": "Model ID",
"AylaHeartBeatFrequency": 0
},
"Product": {
"Mode": 1,
"Model": "abc"
},
"data": {
"DeviceType": 300,
"Endpoint": 0,
"UniID": "0000000000000000"
}
}
You can do:
var map = /*put your json here. You can use json.decode() on the json if it's not yet formatted*/, value;
for(var item in map.values) {
if(item.containsKey('AylaHeartBeatFrequency') value = item['AylaHeartBeatFrequency']) ;
}

The method '[]' can't be unconditionally invoked because the receiver can be 'null' - unable to take the value I need

void main() {
var value = [
{
"abx": [
{
"avv": "blah",
"asd": [
{
"topic":
"Random.",
"alternate": "Random2"
}
]
},
{
"avv1": "bluh",
"asc": [
{
"topic":
"Ran4.",
"alternate": "Ran5"
}
]
},
]
}
];
var word = value[0]['abx'][0]['asd'][0]['topic'];
print(word);
}
I want to be able to access the value of "topic" (which is "Random") but I don't know how to do so. Although the error message tells me to use ? or ! operators, it still does not seem to work. Can someone tell me what the problem is
try this:
void main() {
var value = [
{
"abx": [
{
"avv": "blah",
"asd": [
{
"topic":
"Random.",
"alternate": "Random2"
}
]
},
{
"avv1": "bluh",
"asc": [
{
"topic":
"Ran4.",
"alternate": "Ran5"
}
]
},
]
}
];
var word = ((value[0]['abx'] as List<dynamic>)[0]['asd'] as List<dynamic>)[0]['topic'];
print(word);
}
This error is because of null-safety in Dart. Because you are fetching the values from and List which contains multiple data and any them can be null so it will just want us to ensure that receiver will have some value.
You can solve this error by adding ! or ? in your code right after the receiver like below :
var word = value[0]['abx']![0]['asd']![0]['topic'];
Or
var word = value[0]['abx']?[0]['asd']?[0]['topic'];
Also change the declaration of your variable like :
final List<Map<String, dynamic>> value = [];
Or
final value = [] as List<Map<String, dynamic>>;

Store array of string into the mongoDB collection

I am very new to MongoDB and mongoose I have a model name called agent
agent.model.js
const mongoose = require('mongoose')
const agentSchema = new mongoose.Schema({
agent: {
type: String,
required: true
}
})
const Agent = mongoose.model('Agent', agentSchema)
module.exports = Agent;
Now I have a array of string:
const agentName = ['john', 'alex', 'david'];
Now I want to store this array into the mongoDB as an individual agent.
like this:
[
{
"_id": "6000977d9b94f52960955066",
"agent": "john",
"__v": 0
},
{
"_id": "6000977d9b94f52960955067",
"agent": "alex",
"__v": 0
},
{
"_id": "6000977d9b94f52960955068",
"agent": "david",
"__v": 0
}
]
Note: Right now First I am converting my array of string into the array of object using loop like this:
agentName = agentName.map((e) => {return {agent: e}})
//output of above line of code
[ { agent: 'Alex Watson' },
{ agent: 'John Snow' },
{ agent: 'Rita Ora' } ]
Then I am saving the agentName.
But I am looking for some better approach, Like in which there is no need of converting the array of string into the array of object.
you must to use insertMany() function is used to insert multiple documents into a collection. It accepts an array of documents to insert into the collection. like following code, so have to create a array of abjects, that you created
note: in your question define const agentName next step assign result of map to the constant variable, so this is wrong
const agentName = ['john', 'alex', 'david'];
let arr = agentName.map((e) => {return {agent: e}})
Agent.insertMany(arr).then(function(){
console.log("Data inserted") // Success
}).catch(function(error){
console.log(error) // Failure
});

How to iterate over multiple arrays without nested observables

I must iterate over array, find correspondent objects in other array an merge the result in a object.
Assume I have three arrays
var users = [
{ name: "A", type: 2, level: 1 },
{ name: "B", type: 1, level: 2 }
]
var types = [
{ description: "Type 1", id: 1 },
{ description: "Type 2", id: 2 }
]
var levels = [
{ description: "Level 1", id: 1 },
{ description: "Level 2", id: 1 }
]
I want to have following result:
var users = [
{ name: "A", type: 2, level: 1, levelDescription: "Level 1", typeDescription: "Type 2" },
{ name: "B", type: 1, level: 2, levelDescription: "Level 2", typeDescription: "Type 1" }
]
I know I can achieve it like that
var usersObservable = RX.Observable.fromArray(users);
var typesObservable = Rx.Observable.fromArray(types);
var levelsOBservable = Rx.Observable.fromArray(levels);
var uiUsers= [];// not really needed because I will use the same users array again.
usersObservable.map(function(user) {
typesObservable.filter(function(type) {
return type.id == user.type;
}).subscribeOnNext(function(userType) {
user.typeDescription = userType.description;
});
return user;
}).map(function(user) {
levelsOBservable.filter(function(level) {
return level.id == user.levelId;
}).subscribeOnNext(function(level) {
user.levelDescription = level.description;
});
return user;
})
.subscribeOnNext(function(user) {
uiUsers.push(user);
})
I would like to have a solution without nested Observables.
Thanks.
I am not sure why you are using Rx at all for this problem. You have data in space (i.e. arrays), not data over time (i.e. an observable sequence). But you force these arrays into Rx to then create a very complicated solution.
I think you are looking for something like the answer here https://stackoverflow.com/a/17500836/393615 where you would join the source array types. In your case you just "inner-join" twice to combine all three data sets.
You can archive this by using the switchMap operator that combines the result of a filtered stream with the latest value of the original stream and uses a projection function to merge the results into a single object. This can be generalised in your example such that you can use a generic higher order function in both cases. See fiddle.
Full code (ES2015, RxJS5):
const users = [
{ name: "A", type: 2, level: 1 },
{ name: "B", type: 1, level: 2 }
];
const types = [
{ description: "Type 1", id: 1 },
{ description: "Type 2", id: 2 }
];
const levels = [
{ description: "Level 1", id: 1 },
{ description: "Level 2", id: 2 }
];
const users$ = Rx.Observable.from(users);
const types$ = Rx.Observable.from(types);
const levels$ = Rx.Observable.from(levels);
function join(s$, sourceProperty, targetProperty, streamProperty) {
return function(initObj) {
const stream$ = s$.filter(x => x.id === initObj[sourceProperty]);
return Rx.Observable.combineLatest(
Rx.Observable.of(initObj),
stream$,
(obj, streamObj) => {
const prop = streamObj[streamProperty];
return Object.assign({}, obj, { [targetProperty]: prop });
}
);
};
}
users$
.switchMap(join(types$, 'type', 'typeDescription', 'description'))
.switchMap(join(levels$, 'level', 'levelDescription', 'description'))
.subscribe(x => console.log(x));

Trying to get a count of each word in a MongoDB field is this a job for MapReduce?

I've got a collection with a bunch of body posts in it. For example:
posts = { { id: 0, body: "foo bar baz", otherstuff: {...} },
{ id: 1, body: "baz bar oof", otherstuff: {...} },
{ id: 2, body: "baz foo oof", otherstuff: {...} }
};
I'd like to figure out how to loop through each document in the collection and carry a count of each word in each post body.
post_word_frequency = { { foo: 2 },
{ bar: 2 },
{ baz: 3 },
{ oof: 2 },
};
I've never used MapReduce and I'm still really fresh to mongo, but I'm looking at the documentation on http://cookbook.mongodb.org/patterns/unique_items_map_reduce/
map = function() {
words = this.body.split(' ');
for (i in words) {
emit({ words[i] }, {count: 1});
}
};
reduce = function(key, values) {
var count = 0;
values.forEach(function(v) {
count += v['count'];
});
return {count: count};
};
db.posts.mapReduce(map, reduce, {out: post_word_frequency});
As a bit of an added difficulty, I'm doing it in node.js (with node-mongo-native, though am willing to switch to do the reduce query if there's an easier way).
var db = new Db('mydb', new Server('localhost', 27017, {}), {native_parser:false});
db.open(function(err, db){
db.collection('posts', function(err, col) {
db.col.mapReduce(map, reduce, {out: post_word_frequency});
});
});
So far, I'm having difficulty in that node's telling me ReferenceError: post_word_frequency is not defined (I tried creating it in the shell, but that still didn't help).
So has anyone done a mapreduce with node.js? Is this the wrong use for map reduce? maybe another way to do it? (perhaps just loop and upsert into another collection?)
Thanks for any feedback and advice! :)
EDIT Ryanos below was correct (thanks!) one thing that's missing from my MongoDB based solution was finding the collection and converting it to an array.
db.open(function(err, db){
db.collection('posts', function(err, col) {
col.find({}).toArray(function(err, posts){ // this line creates the 'posts' array as needed by the MAPreduce functions.
var words= _.flatten(_.map(posts, function(val) {
Theres a bug with {out: post_word_frequency} maybe you want {out: "post_word_frequency"} but it should work without this out variable.
Using underscore it can be simply done.
/*
[{"word": "foo", "count": 1}, ...]
*/
var words = _.flatten(_.map(posts, function(val) {
return _.map(val.body.split(" "), function(val) {
return {"word": val, "count": 1};
});
}));
/*
{
"foo": n, ...
}
*/
var count = _.reduce(words, function(memo, val) {
if (_.isNaN(++memo[val.word])) {
memo[val.word] = 1;
}
return memo;
}, {});
Live Example
_.reduce, _.map, _.isNaN, _.flatten