I have to make List<List> using List
List<String> list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10' , '11', '12', '13', '14', '15', '16', '17', '18' , '19', '20', '21', '22', '23', '24', '25'];
list.length will be no more than 25.
have to divide by 5 like
int divide;
divide = word.length ~/ 5;
and have to make List<List>
I don't know how to do it.
have to be
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20],[21, 22, 23, 24, 25]]
if list.length is 23 have to be
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20],[21, 22, 23]]
You can try this one
List dataList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10' , '11', '12', '13', '14', '15', '16', '17', '18' , '19', '20', '21', '22'];
List chunkList = [];
int chunkSize = 5;
for (var i = 0; i < dataList.length; i += chunkSize) {
chunkList.add(dataList.sublist(i, i+chunkSize > dataList.length ? dataList.length : i + chunkSize));
}
print(chunkList);
I think this is the best one, you can try like below
List<List<String>> _getListInList(List<String> data) {
final chunks = <List<String>>[];
final chunkSize = 5;
for (var i = 0; i < data.length; i += chunkSize) {
chunks.add(
data.sublist(
i,
i + chunkSize > data.length ? data.length : i + chunkSize,
),
);
}
return chunks;
}
Just Copy and Paste :D
Related
I have a collection that can contain several million documents, for simplicity, lets say they look like this:
{'_id': '1', 'user_id': 1, 'event_type': 'a', 'name': 'x'}
{'_id': '2', 'user_id': 1, 'event_type': 'b', 'name': 'x'}
{'_id': '3', 'user_id': 1, 'event_type': 'c', 'name': 'x'}
{'_id': '4', 'user_id': 2, 'event_type': 'a', 'name': 'x'}
{'_id': '5', 'user_id': 2, 'event_type': 'b', 'name': 'x'}
{'_id': '6', 'user_id': 3, 'event_type': 'a', 'name': 'x'}
{'_id': '7', 'user_id': 3, 'event_type': 'b', 'name': 'x'}
{'_id': '8', 'user_id': 4, 'event_type': 'a', 'name': 'x'}
{'_id': '9', 'user_id': 4, 'event_type': 'b', 'name': 'x'}
{'_id': '10', 'user_id': 4, 'event_type': 'c', 'name': 'x'}
I want to have a daily job that runs and deletes all documents by user_id, if the user_id has a doc with event_type 'c'
So the resulting collection will be
{'_id': '4', 'user_id': 2, 'event_type': 'a', 'name': 'x'}
{'_id': '5', 'user_id': 2, 'event_type': 'b', 'name': 'x'}
{'_id': '6', 'user_id': 3, 'event_type': 'a', 'name': 'x'}
{'_id': '7', 'user_id': 3, 'event_type': 'b', 'name': 'x'}
I did it successfully with mongoshell like this
var cur = db.my_collection.find({'event_type': 'c'})
ids = [];
while (cur.hasNext()) {
ids.push(cur.next()['user_id']);
if (ids.length == 5){
print('deleting for user_ids', ids);
print(db.my_collection.deleteMany({user_id: {$in: ids}}));
ids = [];
}
}
if (ids.length){db.my_collection.deleteMany({user_id: {$in: ids}})}
Created a cursor to hold all docs with event_type 'c', grouped them into batches of 5 then deleted all docs with these ids.
It works but looks very slow, like each cur.next() only gets one doc at a time.
I wanted to know if there is a better or more correct way to achieve this, if it was elasticsearch I would create a sliced scroll, scan each slice in parallel and submit parallel deleteByQuery requests with 1000 ids each. Is something like this possible/preferable with mongo?
Scale wise I expect there to be several million docs (~10M) at the collection, 300K docs that match the query, and ~700K that should be deleted
It sounds like you can just use deleteMany with the original query:
db.my_collection.deleteMany({
event_type: 'c'
})
No size limitations on it, it might just take a couple of minutes to run depending on instance size.
EDIT:
I would personally try to use the distinct function, it's the cleanest and easiest code. distinct does have a 16mb limit about 300k~ unique ids a day (depending on userid field size) sounds a bit close to the threshold, or past it.
const userIds = db.my_collection.distinct('user_id', { event_type: 'c'});
db.my_collection.deleteMany({user_id: {$in: userIds}})
Assuming you except scale to increase, or this fails your tests then the best way is to use something similar to your approach, just in much larger batches. for example:
const batchSize = 100000;
const count = await db.my_collection.countDocuments({'event_type': 'c'});
let iteration = 0;
while (iteration * batchSize < count) {
const batch = await db.my_collection.find({'event_type': 'c'}, { projection: { user_id: 1}}).limit(batchSize).toArray();
if (batch.length === 0) {
break
}
await db.my_collection.deleteMany({user_id: {$in: batch.map(v => v.user_id)}});
iteration++
}
I have a Map <String,List> map1 that looks like that
{First: ['1', '2', '3', '4'], Second: ['A', 'B']}
I want to create another Map<String,Map<String,int>> as a ruslt of values from map1 to be like that
{'1A' : ['String1':10,'String2':20], '1B' : ['String1':10,'String2':20] , '2A' : ['String1':10,'String2':20], '2B' : ['String1':10,'String2':20], '3A' : ['String1':10,'String2':20] , '3C' : ['String1':10,'String2':20]}
I hope you get my point
Similar question Generate all combinations from multiple lists
Reference Source: https://stackoverflow.com/a/17193002/6576315
void main() async{
Map<String,List> rawMapList = {"First": ['1', '2', '3', '4'], "Second": ['A', 'B']};
List<Map<String, int>> mapResult = [{"String1" : 10}, {"String2" : 20}];
List<String> keyList = <String>[];
generatePermutations(rawMapList.values.toList(), keyList, 0, "");
var result = Map.fromEntries(keyList.map((value) => MapEntry(value, mapResult)));
print(result);
}
void generatePermutations(List<List<dynamic>> lists, List<String> result, int depth, String current) {
if (depth == lists.length) {
result.add(current);
return;
}
for (int i = 0; i < lists.elementAt(depth).length; i++) {
generatePermutations(lists, result, depth + 1, current + lists.elementAt(depth).elementAt(i));
}
}
Try first on DartPad, This code block will print
{1A: [{String1: 10}, {String2: 20}], 1B: [{String1: 10}, {String2: 20}], 2A: [{String1: 10}, {String2: 20}], 2B: [{String1: 10}, {String2: 20}], 3A: [{String1: 10}, {String2: 20}], 3B: [{String1: 10}, {String2: 20}], 4A: [{String1: 10}, {String2: 20}], 4B: [{String1: 10}, {String2: 20}]}
Do upvote reference
the solution
Map<String, dynamic> data = {
'First': ['1', '2', '3', '4'],
'Second': ['A', 'B']
};
Map<String, dynamic> ans = {};
calculate() {
for (var i in (data['First'] as List<dynamic>)) {
for (var j in (data['Second'] as List<dynamic>)) {
ans.addAll({
"$i$j": [
{'String1': 10},
{'String2': 20}
],
});
}
}
log("$ans");
}
I have two lists, 1 is a list of Map items, and another list which is the order.
I would like to sort the items based on their description attribute and compare them with the order list and have them inserted at the top.
import 'package:collection/collection.dart';
void main() {
List<String> order = [
'top european',
'top usa',
'top rest of the world'
];
List<Map> items = [
{'id': 0, 'id2': 5, 'description': 'Top USA'},
{'id': 2, 'id2': 2, 'description': 'Top A'},
{'id': 3, 'id2': 0, 'description': 'Top Z'},
{'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
{'id': 4, 'id2': 4, 'description': 'Top C'},
{'id': 5, 'id2': 1, 'description': 'Top D'},
{'id': 1, 'id2': 3, 'description': 'Top European'},
];
//this works but adds the items at the end
items.sort((a,b) {
return order.indexOf(a['description'].toLowerCase()) -
order.indexOf(b['description'].toLowerCase());
});
///Results: print(items);
// List<Map> items = [
// {'id': 2, 'id2': 2, 'description': 'Top A'},
// {'id': 3, 'id2': 0, 'description': 'Top Z'},
// {'id': 4, 'id2': 4, 'description': 'Top C'},
// {'id': 5, 'id2': 1, 'description': 'Top D'},
// {'id': 1, 'id2': 3, 'description': 'Top European'},
// {'id': 0, 'id2': 5, 'description': 'Top USA'},
// {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
// ];
}
SOLUTION: I also tried this approach which is not ideal, but it works.
List <Map> itemsOrder = items
.where(
(ele) => order.contains(ele['description'].toString().toLowerCase()))
.toList();
itemsOrder.sort((a, b) {
return order.indexOf(a['description'].toLowerCase()) -
order.indexOf(b['description'].toLowerCase());
});
items.removeWhere(
(ele) => order.contains(ele['description'].toString().toLowerCase()));
itemsOrder = itemsOrder.reversed.toList();
for (int i = 0; i < itemsOrder.length; i++) {
items.insert(0, itemsOrder[i]);
}
///Results: print(items);
// List<Map> items = [
// {'id': 1, 'id2': 3, 'description': 'Top European'},
// {'id': 0, 'id2': 5, 'description': 'Top USA'},
// {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
// {'id': 2, 'id2': 2, 'description': 'Top A'},
// {'id': 3, 'id2': 0, 'description': 'Top Z'},
// {'id': 4, 'id2': 4, 'description': 'Top C'},
// {'id': 5, 'id2': 1, 'description': 'Top D'},
// ];
Ideally, I would like to use sortBy or sortByCompare but unfortunately, I cannot find a proper example or get a grasp of how to use it.
The way I would fix this is to find the index of the description in the order list and if it cannot be found, I would use a number that is out of index inside the order list to indicate that this item should be at the bottom of the list.
This would be my solution:
void testIt() {
final outOfBounds = order.length + 1;
const description = 'description';
items.sort(
(lhs, rhs) {
final lhsDesc = (lhs[description] as String).toLowerCase();
final rhsDesc = (rhs[description] as String).toLowerCase();
final lhsIndex =
order.contains(lhsDesc) ? order.indexOf(lhsDesc) : outOfBounds;
final rhsIndex =
order.contains(rhsDesc) ? order.indexOf(rhsDesc) : outOfBounds;
return lhsIndex.compareTo(rhsIndex);
},
);
}
And the result is:
[{id: 1, id2: 3, description: Top European}, {id: 0, id2: 5, description: Top USA}, {id: 6, id2: 6, description: Top Rest of the world}, {id: 2, id2: 2, description: Top A}, {id: 3, id2: 0, description: Top Z}, {id: 4, id2: 4, description: Top C}, {id: 5, id2: 1, description: Top D}]
Trying to make list inside a list so if:
List<String> dataList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10' , '11', '12', '13', '14', '15', '16', '17', '18' , '19', '20', '21', '22'];
List<int> dataListLength = [5 , 7, 10];
List<List<String>> listList = [];
I want it like this:
listList[0] -> ['1', '2', '3', '4', '5'],
listList[1] -> ['6', '7', '8', '9', '10' , '11', '12']
listList[2] -> ['13', '14', '15', '16', '17', '18' , '19', '20', '21', '22']
try below code.
i think you can use this function List.getRange(int, int)
In Dart, you don't need to specify the list size.
void main() {
List<String> dataList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10' , '11', '12', '13', '14', '15', '16', '17', '18' , '19', '20', '21', '22'];
List<List> listList = [dataList.getRange(0,4).toList(),
dataList.getRange(5,11).toList(),
dataList.getRange(11,21).toList()];
print(listList);
}
Try this
List<String> dataList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10' , '11', '12', '13', '14', '15', '16', '17', '18' , '19', '20', '21', '22'];
List<int> dataListLength = [5 , 7, 10];
List<List<String>> listList = [];
int start = 0;
for(var i in dataListLength){
List<String> temp = [];
for(int j=start; j<i+start; j++){
temp.add(dataList[j]);
}
listList.add(temp);
start += i;
}
print(listList);
result
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]]
clique_bait.page_hierarchy
CREATE TABLE clique_bait.page_hierarchy (
"page_id" INTEGER,
"page_name" VARCHAR(14),
"product_category" VARCHAR(9),
"product_id" INTEGER
);
sample input
('1', 'Home Page', null, null),
('2', 'All Products', null, null),
('3', 'Salmon', 'Fish', '1'),
('4', 'Kingfish', 'Fish', '2'),
('5', 'Tuna', 'Fish', '3'),
('6', 'Russian Caviar', 'Luxury', '4'),
('7', 'Black Truffle', 'Luxury', '5'),
clique_bait.events
CREATE TABLE clique_bait.events (
"visit_id" VARCHAR(6),
"cookie_id" VARCHAR(6),
"page_id" INTEGER,
"event_type" INTEGER,
"sequence_number" INTEGER,
"event_time" TIMESTAMP
);
sample input:
('ccf365', 'c4ca42', '1', '1', '1', '2020-02-04 19:16:09.182546'),
('ccf365', 'c4ca42', '2', '1', '2', '2020-02-04 19:16:17.358191'),
('ccf365', 'c4ca42', '6', '1', '3', '2020-02-04 19:16:58.454669'),
('ccf365', 'c4ca42', '9', '1', '4', '2020-02-04 19:16:58.609142'),
('ccf365', 'c4ca42', '9', '2', '5', '2020-02-04 19:17:51.72942'),
('ccf365', 'c4ca42', '10', '1', '6', '2020-02-04 19:18:11.605815'),
('ccf365', 'c4ca42', '10', '2', '7', '2020-02-04 19:19:10.570786'),
('ccf365', 'c4ca42', '11', '1', '8', '2020-02-04 19:19:46.911728'),
('ccf365', 'c4ca42', '11', '2', '9', '2020-02-04 19:20:45.27469'),
('ccf365', 'c4ca42', '12', '1', '10', '2020-02-04 19:20:52.307244'),
('ccf365', 'c4ca42', '13', '3', '11', '2020-02-04 19:21:26.242563'),
('d58cbd', 'c81e72', '1', '1', '1', '2020-01-18 23:40:54.761906'),
('d58cbd', 'c81e72', '2', '1', '2', '2020-01-18 23:41:06.391027'),
('d58cbd', 'c81e72', '4', '1', '3', '2020-01-18 23:42:02.213001'),
('d58cbd', 'c81e72', '4', '2', '4', '2020-01-18 23:42:02.370046'),
('d58cbd', 'c81e72', '5', '1', '5', '2020-01-18 23:42:44.717024'),
('d58cbd', 'c81e72', '5', '2', '6', '2020-01-18 23:43:11.121855'),
('d58cbd', 'c81e72', '7', '1', '7', '2020-01-18 23:43:25.806239'),
('d58cbd', 'c81e72', '8', '1', '8', '2020-01-18 23:43:40.537995'),
('d58cbd', 'c81e72', '8', '2', '9', '2020-01-18 23:44:14.026393'),
('d58cbd', 'c81e72', '10', '1', '10', '2020-01-18 23:44:22.103768'),
('d58cbd', 'c81e72', '10', '2', '11', '2020-01-18 23:45:00.004781'),
('d58cbd', 'c81e72', '12', '1', '12', '2020-01-18 23:45:38.186554')
clique_bait.event_identifier
CREATE TABLE clique_bait.event_identifier (
"event_type" INTEGER,
"event_name" VARCHAR(13)
);
Sample input
('1', 'Page View'),
('2', 'Add to Cart'),
('3', 'Purchase'),
('4', 'Ad Impression'),
('5', 'Ad Click');
The output i need is
Visit_id, Page_name which are added to cart concatenated with commas
my query
select visit_id, string_agg(page_name::character varying, ',')
within group (order by sequence_number) as cart_items
from clique_bait.events e
join clique_bait.page_hierarchy ph
on e.page_id = ph.page_id
join clique_bait.event_identifier ei
on ei.event_type = e.event_type
where event_name = 'Add to Cart'
group by visit_id
is not working, error: function string_agg(character varying, unknown, integer) does not exist
Give this a shot:
select visit_id, string_agg(page_name, ',' order by sequence_number) as cart_items
from events e
join page_hierarchy ph on e.page_id = ph.page_id
join event_identifier ei on ei.event_type = e.event_type
where event_name = 'Add to Cart'
group by visit_id
The order by sequence_number within the string_agg(...) function will sort your comma separated output based on sequence number.
Here's an example with the sample data you provided:
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=52077d5be605a51d3a7bb14152a392df
Here're the results of that:
visit_id | cart_items
:------- | :------------
d58cbd | Kingfish,Tuna