How to reverse Map values in dart - flutter

I am trying to reverse Map values. But didin't get proper one,
here my Map
Map<String, dynamic> details = {
"sms": {
"very_low": false,
"low": false,
"medium": false,
"high": false,
"very_high": true
}
};
I want to get like this ;
{
sms: {
very_high: true,
high: false,
medium: false,
low: false,
very_low: false
}
}
If Anyone please share your ideas

Let's say this is your "map":
Map<String, dynamic> details = {
"sms": {
"very_low": false,
"low": false,
"medium": false,
"high": false,
"very_high": true
}
};
You can use this extension:
extension NewMap on Map {
Map reverse() => Map.fromEntries(entries.toList().reversed);
}
and use it like this:
details["sms"] = (details["sms"] as Map<String, dynamic>).reverse();
print("details =$details"); //details = {sms: {very_high: true, high: false, medium: false, low: false, very_low: false}}

A solution that works for any Map no matter how much nested it is:
Object reverse(Object object) {
if (object is Map) {
return Map.fromEntries(object.entries.map((e) => MapEntry(e.key, reverse(e.value))).toList().reversed);
}
return object;
}
usage:
void main() async {
Map<String, dynamic> details = {
"sms": {
"very_low": false,
"low": false,
"medium": false,
"high": false,
"very_high": true
}
};
var newDetails = reverse(details);
print(details);
//{sms: {very_low: false, low: false, medium: false, high: false, very_high: true}}
print(newDetails);
//{sms: {very_high: true, high: false, medium: false, low: false, very_low: false}}
}

final details =
{"sms" : {"very_low" : false, "very_hight" : true, "very_medium" : false} };
final outerMap = {};
for(final m in details.entries){
final reversedList = m.value.entries.toList().reversed;
final innerMap = {};
innerMap.addEntries(reversedList);
outerMap.addAll({m.key : innerMap});
}
print(outerMap);
//details = {sms: {very_medium: false, very_hight: true, very_low: false}}

import 'dart:convert';
Map<String, dynamic> yourMap = {
"sms": {
"very_low": false,
"low": false,
"medium": false,
"high": false,
"very_high": true
}
};
Map<K, V> reverse<K, V>(Map<K, V> source) {
return Map<K, V>.fromEntries(source.entries.toList().reversed);
}
main() {
print(jsonEncode(yourMap));
yourMap['sms'] = reverse(yourMap['sms']);
print(jsonEncode(yourMap));
}
Prints:
{"sms":{"very_low":false,"low":false,"medium":false,"high":false,"very_high":true}}
{"sms":{"very_high":true,"high":false,"medium":false,"low":false,"very_low":false}}
Please note that this only works because Map behind the scenes constructs a LinkedHashMap that is insertion-ordered. If you construct other types of Map that are not, this may not work. Generally speaking, it might be wise to not rely on the order of items in a Map because it is not guaranteed unless you created the Map yourself.
Since this looks like it should be JSON: don't bother sorting this. It is supposed to be a machine-to-machine protocol, machines do not care if it looks neat. The less uneccessary code you write, the less bugs you produce.

Related

Prisma Client Select query on existence of value in joined table via Schema

In my instance i have a schema joining bonuses to a casino. query works great for data but I am unable to filter via the query itself. The where clause I used appears to be correct but I get an error the stating Object literal may only specify known properties, and 'nodeposit' does not exist in type. But I can query that data.
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
nodeposit: { gt : 0 },
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: {
where: {
nodeposit: { gt: 0 },
},
},
},
take: 14,
});
If I remove the bonus pard in the WHERE clause the query works as expected but I want to grab all bonuses for each casino, but only if the bonuses contains a nodeposit value.
This nis what I want to use.
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
nodeposit: { gt : 0 },
},
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: true,
},
take: 14,
});
SCHEMA :
model casino_p_casinos {
id Int #id #default(autoincrement())
casino String?
type String?
url String?
bonuses casino_p_bonus[]
model casino_p_bonus {
id Int #id #default(autoincrement())
parent Int
game String?
freespins Int?
freeplay String?
nodeposit Int?
deposit Int?
casino_p_casinos casino_p_casinos #relation(fields: [parent], references: [id])
}
You have a one to many relation, so when you add a where clause, you have one more layer with some, every or none like
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
// 'some' can be replaced by 'every' or 'none' here
some: {
nodeposit: { gt: 0 }
}
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: true
},
take: 14
})
This query will filter casinos where some nodeposit are greater than 0 and return all bonuses, even those who are equals to 0.
And then, if you only want bonuses with nodeposit greater than 0 in casinos that have some, you should do:
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
// 'some' can be replaced by 'every' or 'none' here
some: {
nodeposit: { gt: 0 }
}
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: {
where: {
nodeposit: { gt: 0 }
}
}
},
take: 14
})

How to create or update within object of objects

I'm trying to access a database with the following difficult schema and want to update the file_name value if it exists, or create a new object with the file_name if it does not. As I have searched, the option { upsert: true, new: true, setDefaultsOnInsert: true }; will update do the second bit, but the problem is how do you access the file_name key nested deep within.
export type _ID = string;
export interface FileSchema {
[_id: _ID]: {
file_name: string;
creation_date: Date;
isPublished: boolean;
content: string;
};
}
export interface AccountSchema {
...
files: FileSchema;
}
const accountSchema = new Schema<AccountSchema>({
...
files: {
type: Map,
unique: true,
of: {
file_name: {
type: String,
required: true,
minlength: 4,
maxlength: 60,
unique: true,
},
creation_date: {
type: Date,
required: true,
},
isPublished: {
type: Boolean,
required: true,
},
content: {
type: String,
required: true,
},
},
},
});
Not familiar with Mongoose but you may be missing dot notation to access nested fields, look at
https://www.mongodb.com/docs/manual/tutorial/query-embedded-documents/#specify-equality-match-on-a-nested-field
I've searched a bit, and have come up with the solution below, although not pretty due to multiple queries. For nested objects with a dynamic key, you must use codes like [files.${file_id}.file_name] (with ``) to access the object within.
Reference 1
Reference 2
const accountSchema = new Schema<AccountSchema>({
...
files: {
type: Schema.Types.Map,
unique: true,
of: Object,
},
})
// checks if file exists, if exist then update file_name
const files: FileSchema | null = await DB_ACCOUNT.findOneAndUpdate(
{
_id,
username,
[`files.${file_id}`]: { $exists: true },
},
{
$set: {
[`files.${file_id}.file_name`]: file_name,
},
},
{ new: true, upsert: false, useFindAndModify: false }
);
const fn = genObjectId().toString();
// if file does not exist, then create a new file
const x = await DB_ACCOUNT.findOneAndUpdate(
{
_id,
username,
},
{
$set: {
[`files.${fn}`]: {
file_name,
creation_date: new Date(),
isPublished: false,
content: "",
},
},
},
{ new: true, upsert: true }
)
console.log("X: ", x);

How to access the values only in flutter map

"turf_amenities": {
"turf_washroom": true,
"turf_water": true,
"turf_dressing": false,
"turf_parking": true,
"turf_gallery": true,
"turf_cafeteria": true
},
You can get the bool list like
final bools = data["turf_amenities"]?.values.toList();
print(bools);
final data = {
"turf_amenities": {
"turf_washroom": true,
"turf_water": true,
"turf_dressing": false,
"turf_parking": true,
"turf_gallery": true,
"turf_cafeteria": true
},
};
final values = data.values.toList();
print(
values); //[{turf_washroom: true, turf_water: true, turf_dressing: false, turf_parking: true, turf_gallery: true, turf_cafeteria: true}]
final bools = data["turf_amenities"]?.values.toList();
print(bools); //[true, true, false, true, true, true]

Accessing Flutter callkit Incoming Calls Params

am at the moment making use of this particular flutter package for my project but I can't access the params, please I really need your help
flutter_callkit_incoming: ^1.0.0+8
when am to receive an incoming call I use the below code
this._currentUuid = _uuid.v4();
var params = <String, dynamic>{
'id': _currentUuid,
'nameCaller': data.fromFullName,
'appName': 'Prayer Buddy',
'avatar': data.fromImage,
'handle': 'Prayer Partner Calling',
'type': type,
'duration': 30000,
'extra': <String, dynamic>{'userId': '1a2b3c4d'},
'headers': <String, dynamic>{'apiKey': 'Abc#123!', 'platform': 'flutter'},
'android': <String, dynamic>{
'isCustomNotification': true,
'isShowLogo': false,
'ringtonePath': 'ringtone_default',
'backgroundColor': '#0955fa',
'backgroundUrl': data.toImage,
'actionColor': '#4CAF50'
},
'ios': <String, dynamic>{
'iconName': 'AppIcon40x40',
'handleType': 'generic',
'supportsVideo': true,
'maximumCallGroups': 2,
'maximumCallsPerCallGroup': 1,
'audioSessionMode': 'default',
'audioSessionActive': true,
'audioSessionPreferredSampleRate': 44100.0,
'audioSessionPreferredIOBufferDuration': 0.005,
'supportsDTMF': true,
'supportsHolding': true,
'supportsGrouping': false,
'supportsUngrouping': false,
'ringtonePath': 'Ringtone.caf'
}
};
await FlutterCallkitIncoming.showCallkitIncoming(params);
on the FlutterCallkitIncoming.onEvent.listen((event) function am trying to access the params sent via the showCallkitIncoming(params)
so i did a print of the event print(event) the output was below
{ event: com.hiennv.flutter_callkit_incoming.ACTION_CALL_ENDED, body: {duration: 30000, extra: {userId: 1a2b3c4d}, uuid: 1fa5d670-5698-40fa-8705-bd794304fa96, avatar: http://arome.joons-me.com/user_img/james/images/image_picker_F27FD117-E882-4C51-9143-943E3BF4A8CF-24547-00000899F347179A.jpg, type: 0, nameCaller: James Amadin, handle: Prayer Partner Calling, appName: Prayer Buddy, ios: {supportsHolding: true, audioSessionPreferredIOBufferDuration: 0.005, supportsDTMF: true, maximumCallGroups: 2, includesCallsInRecents: true, audioSessionPreferredSampleRate: 44100.0, iconName: AppIcon40x40, supportsVideo: true, supportsGrouping: false, audioSessionActive: true, audioSessionMode: default, maximumCallsPerCallGroup: 1, supportsUngrouping: false, handleType: generic, ringtonePath: Ringtone.caf}} }
I want to access the extra from the return JSON, please how do I do that?
but when i tried to access it via the below code
try {
dynamic myMap = json.decode(event!.body);
if (myMap is! Map<String, dynamic>) throw FormatException();
final message = myMap['extra'];
print('1message == ${message}');
} catch (error) {
print('JSON is in the wrong format');
}
I got JSON is in the wrong format
I was able to resolve it by the following code
print(event!.body['extra']['userId']);
print(event.body['extra']['to_user']);
print(event.body['extra']['from_user']);

Populate none ref objects of a nested array

I'm working on a project that uses:
"#nestjs/core": "^7.0.0",
"#nestjs/mongoose": "^7.0.0",
"mongoose": "^5.9.12",
// ...
"typescript": "^3.7.4",
With mongoose/mongoDB config:
uri: MONGO_DB_URI,
useUnifiedTopology: true,
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true,
I'm trying to build a simple CRUD for this model:
export const ContactSchema = new mongoose.Schema(
{
source_id: { type: String, required: true },
firstName: { type: String, trim: true },
lastName: { type: String, trim: true },
phones: [
{
number: {
type: String,
required: true,
unique: true,
validate: {
validator: function(value) {
const phoneNumber = parsePhoneNumberFromString(value)
return phoneNumber && phoneNumber.isValid()
},
},
},
type: {
type: String,
default: function() {
return parsePhoneNumberFromString(this.number).getType() || "N/A"
},
},
code: {
type: Number,
default: function() {
return parsePhoneNumberFromString(this.number).countryCallingCode || undefined
},
},
national: {
type: Number,
default: function() {
return parsePhoneNumberFromString(this.number).nationalNumber || undefined
},
},
},
],
email: { type: String, unique: true, required: true, lowercase: true, trim: true },
},
{ timestamps: true },
)
ContactSchema.plugin(mongoosePaginate)
Like every CRUD app, I'm willing to have fildAll() & fildOne() routes that return the body of a given Contact with all his info including the list of its phone numbers. So I used:
// ...
async findAll(): Promise<Contact[]> {
return this.contactModel.find()
// then I add
.populate('phones')
}
async findBySourceId(id: string): Promise<Contact> {
return this.contactModel.findOne({ source_id: id })
// then I add
.populate('phones')
}
// ...
All info are well saved in the DB and there is no missing data (neither phones) and I'm sure that it works the beginning without even adding .poplate('x'), but that changed somewhere and it returns now unpopulated phone array.
Now It returns:
{
"_id": "5ebc22072e18637d84bcf6f0",
"firstName": "Maher",
"lastName": "Boubakri",
"phones": [],
"email": "mhb#test.im",
// ...
}
But, It should return:
{
"_id": "5ebc22072e18637d84bcf6f0",
"firstName": "Maher",
"lastName": "Boubakri",
"phones": [
{
"_id": "5ebc22072e18637d8fd948f9",
"number": "+21622123456",
"code": 216,
"type": "MOBILE",
"national": 22123456,
}
],
"email": "mhb#test.im",
// ...
}
Note: It is clear that MongoDB generates _id for every phone object, but, it is not a ref Object.
Any idea will be so helpful,
Thank you.
populate is used to join two (or more) collections using the references
here you don't have any references, so you don't need it
just use find() without populate
Based on #Mohammed 's comment and answer, adding .lean() after updating mongoose fixed the problem.
// ...
async findAll(): Promise<Contact[]> {
return this.contactModel.find().lean()
}
async findBySourceId(id: string): Promise<Contact> {
return this.contactModel.findOne({ source_id: id }).lean()
}
// ...