RxJS filter a list based on a list - reactive-programming

If I have a list where the number of arguments vary (or can be updated):
SomeDynamicListofPreferences = [
'Chocolate',
'Strawberry',
'Vanilla'
];
What (if any) would be a good RxJS way to dynamically filter a list of matches based on a main source stream?
StockedFlavors = [
'Almond Mocha',
'Banana',
'Butter Pecan',
'Chocolate',
'Coconut Cream',
...
'Strawberry',
'Vanilla'
];
Ex: Based on what I've learned so far one possibility is:
let dynamicPreferences = Rx.Observable.fromArray(SomeDynamicListofPreferences);
let StockedStream = Rx.Observable.fromArray(StockedFlavors);
let PrefMatches = StockedStream.filter((flavor) =>
dynamicPreferences.includes(flavor) ).
subscribe((x) => { if(x){ /*...do stuff */ }});
The "includes" operator feels like a loop within a loop. I could see another scenario of iterating the raw SomeDynamicListofPreferences to generate individual filterStreams.
Any help regarding technique and/or scale is greatly appreciated.

this works for me... ymmv
function deferSource(source) {
// wrapping in the defer gives us a unique snowflake observable
return Rx.Observable.defer(function() {
// your returned observable may vary as well...
return Rx.Observable.fromArray(source);
})
}
// your observable sources may vary
var preferenceList = [
'Chocolate',
'Strawberry',
'Vanilla'
];
var flavorList = [
'Almond Mocha',
'Banana',
'Butter Pecan',
'Chocolate',
'Coconut Cream',
'Strawberry',
'Vanilla Bean'
];
var prefrence$ = deferSource(preferenceList)
var flavor$ = deferSource(flavorList);
function curryQuery(static$source) {
return function querySourceForResults(dynamic_element) {
return static$source
.filter(function(static_element){
return static_element.includes(dynamic_element)
})
}
}
prefrence$.flatMap(curryQuery(flavor$)).subscribe(logger('result'))

Related

react-query: accessing the query with matching condition (by 1st index of queryKey array)

I've queries like:
useQuery(['myquery',{test:1}], fetchFn)
useQuery(['myquery',{test:2}], fetchFn)
useQuery(['myquery',{test:3}], fetchFn)
I would like to observe the data of all those queries with myquery without knowing the rest of the items of queryKey.
In documentation, as I understood it is possible to observe multiple queries but my matching condition seems not covered.
const observer = new QueriesObserver(queryClient, [
{ queryKey: ['post', 1], queryFn: fetchPost },
{ queryKey: ['post', 2], queryFn: fetchPost },
])
const unsubscribe = observer.subscribe(result => {
console.log(result)
unsubscribe()
})
I could only find similar usage for useIsFetching but it only gives a number of matching queries:
// How many queries matching the posts prefix are fetching?
const isFetchingPosts = useIsFetching(['posts'])
But I want to access the result of the queries, specifically the last updated one.
This is the best thing i can come up with using queryClient :
const Component = () => {
// match all queries with:
const keyPrefix = "courseSection_list";
// since it is loading state, it will trigger twice for each returning result
const matchingQueriesUpdated = useIsFetching([keyPrefix]);
const data = useMemo(() => {
const lastUpdatedMatchingQuery = queryClient.queryCache.queries
.filter((q) => q.queryKey[0] === keyPrefix)
.sort((a, b) => b.state.dataUpdatedAt - a.state.dataUpdatedAt)[0] // sorting puts the last updated one to the 1st index;
return lastUpdatedMatchingQuery.state.data;
}, [matchingQueriesUpdated]);
return <div> bla bla </div>
}
Extra render can be prevented by catching dataUpdatedAt value at 0 for loading state. But i rather keep my code more simple for now.

InstantSearch.js custom widget increase returned results

As you can see in the code bellow, I made 2 custom widgets, one for searching one for displaying results, but I cannot increase the limit of the returned results. When the page loads, it automatically makes a request and retrieves the default results with no query.
We have more than 500+ results which all have to be displayed on the UI, and I cannot modify the limit of the results anywhere. The limit is always 200. As a backend, I am not using algolia but rather meilisearch, but I do not this impacts this in any way.
As you can see in the images, the searchParamters are modified and set to limit 1000, but when the request is made, it sends it as 200.
const search = instantsearch({
indexName: "store",
searchClient: instantMeiliSearch(m_host, m_key),
});
search.addWidgets([
configure({
hitsPerPage: 1000,
limit: 1000,
filters: `image!=null AND is_active=1 AND (countries_ids=${country_id} OR countries_ids=0) AND goto_link != null`,
attributesToHighlight: [],
paginationLimitedTo: 1000,
}),
{
init: function (opts) {
const helper = opts.helper;
const input = document.querySelector('#searchbox');
input.addEventListener('input', function (e) {
helper.setQuery(e.currentTarget.value) // update the parameters
.search(); // launch the query
});
}
},
{
render: function (opts) {
let results = opts.results;
// read the hits from the results and transform them into HTML.
let res = toArray(groupBy(filter_stores(results.hits), 'category_id'));
$(`.stores-list`).empty()
$(`.categories-list`).hide()
res = res.map(it => {
let copy = it;
copy[1] = _.orderBy(it[1].map(store => {
store.default_rank = store.hasOwnProperty(`rank_country_${country_id}`) ? store[`rank_country_${country_id}`] : store.default_rank;
return store;
}), 'default_rank', 'asc');
return copy;
});
res.map(pairs => {
let [category_id, stores] = pairs;
$(`#category_${category_id}`).show()
let html = stores.map(h => create_store(h)).join('')
$(`#store_list_${category_id}`).html(html)
});
},
}
]);
search.start();

How to search a list of Object by another list of items in dart

How to search a list of a class object with one of its property matching to any value in another list of strings
I am able to get filtering based on a single string , but not on a list of strings
final List<shop_cart.ShoppingCart> cartprd = snapshot.documents
.map((f) => shop_cart.ShoppingCart.fromMap(f.data))
.toList();
List<SomeClass> list = list to search;
List<String> matchingList = list of strings that you want to match against;
list.where((item) => matchingList.contains(item.relevantProperty));
If the number of items in list is large, you might want to do:
List<SomeClass> list = list to search;
List<String> matchingList = list of strings that you want to match against;
final matchingSet = HashSet.from(matchingList);
list.where((item) => matchingSet.contains(item.relevantProperty));
Or else just always store the matching values as a hashset.
In case if you want to check for a value in a list of objects . you can follow this :
List rows = [
{"ags": "01224", "name": "Test-1"},
{"ags": "01224", "name": "Test-1"},
{"ags": "22222", "name": "Test-2"},
];
bool isDataExist(String value) {
var data= rows.where((row) => (row["name"].contains(value)));
if(data.length >=1)
{
return true;
}
else
{
return false;
}
}
you can put your own array of objects on rows . replace your key with name . you can do your work based on true or false which is returned from the function isDataExist
As of today, you can't.
(A side note : You can use .where, .singleWhere, .firstWhere. This site explains various list/array methods.)
You can simply use List.where() to filter a list
final List<shop_cart.ShoppingCart> cartprd = snapshot.documents
.where((f) => shop_cart.ShoppingCart.contains(f.data));
var one = [
{'id': 1, 'name': 'jay'},
{'id': 2, 'name': 'jay11'},
{'id': 13, 'name': 'jay222'}
];
int newValue = 13;
print(one
.where((oldValue) => newValue.toString() == (oldValue['id'].toString())));
OUTPUT : ({id: 13, name: jay222})
store output in any variable check if variable.isEmpty then new value is unique either
var checkValue = one
.where((oldValue) => newValue.toString() == (oldValue['id'].toString()))
.isEmpty;
if (checkValue) {
print('Unique');
} else {
print('Not Unique');
}
OUTPUT : Not Unique

meteor, using _.map when joining collections

Here is my helpers to diplay data from two collections
Template.Lirescategorie.helpers({
scategories: function () {
var cursor = Scategories.find();
var data = [];
cursor.forEach(function(somewhat) {
var categories = Categories.findOne({_id : somewhat.categorieID}, {categorie:1});
data.push({cat : categories.categorie, scat : somewhat.scategorie });
});
return data;
}
});
Here are my collections
categorie :
{
"_id": "LBKZQfZZSf4DRdeXo",
"categorie": "Citoyenneté"
}
scategorie
{
"_id": "cNHYpAEvC9ffjWkf5",
"categorieID": "LBKZQfZZSf4DRdeXo",
"scategorie": "Etat-Civil"
}
I'm pretty sure my helpers' code is not optimal. And i think by using _.map or something like that i can reduce the code.
Since i'm not really familiar to it, i'm looking for help about this.
Welcome to client-side joins. You can use .map() to get the list of categorieIDs and do the second find in one go with $in::
var cursor = Scategories.find();
var arrayOfCategorieIDs = cursor.map(function(s){return s.categorieId});
var categories = Categories.find({_id : {$in: arrayOfCategorieIDs}});
Then:
var sCategories = cursor.map(function(s){return s.scategorie}); // array of scategorie names
var categoryNames = categories.map(function(c){return s.categorie}); // array of categorie names
Then assemble these two arrays of strings into the array of objects you're looking for.
But there's a far simpler pattern for a client-side join: just iterate over one cursor and do the lookup into the related collection in a helper. For example:
html:
{{#each sCategories}}
{{sCategorie}}
{{categorie}}
{{/each}}
js:
Lirescategorie.helpers({
sCategories:(){
return Scategories.find();
},
categorie:(){
return Categories.findOne(this.categorieID).categorie;
}
});

Picking an array of hashes from a hash

I have a hash coming back from an XML datasource that looks like this:
{...,
'records' :{
'record' :[
{'availability' :{'$t' :'available'}, ...},
{'availability' :{'$t' :'available'}, ...}
]
}
};
I'd like to get all the record hashes into an array so I can filter() it and do some other operations. However, when I have this statement in my pre block,
raw_records = raw.pick("$..record");
the array that gets returned is an array of two empty strings:
var raw_records = ['', ''];
The odd thing is that I can pick out just availability with expected results:
availability = raw.pick("$..availability.$t");
producing
var availability = ['available', 'available'];
What's wrong with my first pick()?
EDIT: Here is a more complete version that should help with reproducing the problem. It's slightly different, since I'm using the JSON version of the web service now:
global {
datasource hbll <- "https://svc.lib.byu.edu/services/catalog/v1/search/?field=isbn&format=json&terms=";
}
rule new_rule {
select when pageview "amazon.com/.*/?dp/(.*)/" setting (isbn)
pre {
//This is the array with two empty strings...
raw = datasource:hbll(isbn);
myfilter = function(x) { x.pick("availability") eq "available"; };
records = raw.filter(myfilter);
len = records.length();
availability = records.pick("$..availability");
middleman = len > 1 => availability[0] | availability;
available = middleman eq "available" => true | false;
url_list = records.pick("$..url");
url = len > 1 => url_list[0] | url_list;
msg = <<
<p>This book is available for checkout at the BYU Library.</p>
More information
>>;
}
notify("BYU Harold B. Lee Library", msg) with sticky=true;
}
I'm going to need a more complete example. The test app and results I got are below:
ruleset a8x167 {
meta {
name "Pick - Array of Hashes"
description <<
Testing
>>
author "Sam Curren"
logging on
}
dispatch {}
global {
raw = {
'records' :{
'record' :[
{'availability' :{'$t' :'available'}},
{'availability' :{'$t' :'available'}}
]
}
};
}
rule test {
select when pageview ".*" setting ()
pre {
raw_records = raw.pick("$..record");
availability = raw.pick("$..availability.$t");
}
notify("Hello World", "This is a sample rule.");
}
}
And Results:
var raw_records = [{'availability' :{'$t' :'available'}}, {'availability' :{'$t' :'available'}}];
var availability = ['available', 'available'];