How can I query by a array with size in a range?
Documents:
Foo { foo_array: [{name: "item_1"},{name: "item_2}] }
Foo { foo_array: [{name: "item_1"}] }
Foo { foo_array: [{name: "item_1"},{name: "item_2},{name: "item_3}] }
For instance, I try to get: Foo objects which foo_array field has between 2 or 3 items.
Something like:
Foo.where(:foo_array.with_size => [2,3])
You can query arrays by index and then check if the element at the desired index exists. For example:
Foo.where(
# something at index 1 means that the size is at least two
'foo_array.1' => { :$exists => true },
# nothing at index 3 means that the size is at most three
'foo_array.3' => { :$exists => false }
)
Related
In my state I have an object called foodLog which holds all entries a user enters with one of the keys being foodSelectedKey and I'm trying to return all entries that have a matching value from that key with a different array called foodFilter.
However, this doesn't work and errors out saying foodLog.filter() isn't a function - I've looked this up and it's because it's an Object (I think). Any help would be greatly appreciated!
state = {
// log food is for the logged entries
foodLog: {},
// used for when filtering food entries
foodFilter: [],
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.filter((item) => {
return foodLog.foodsSelectedKey.map((food) => {
return foodFilter.includes(food);
});
});
};
I guess the reason behind the error Is not a function is that the object can not be looped. By that it means you can not iterate an object with differend variables inside, if it has no index to be iterated like an array. The same goes for map(), find() and similar functions which MUST be run with arrays - not objects.
As far as I understand you have an object named foodLog which has an array named foodsSelectedKey. We need to find intersected elements out of foodFilter with the array. This is what I came up with:
state = {
// log food is for the logged entries
foodLog: {
foodsSelectedKey: [
{ id: 1, name: "chicken" },
{ id: 2, name: "mashroom" }
]
},
// used for when filtering food entries
foodFilter: [
{ id: 1, name: "chicken" },
{ id: 2, name: "orange" }
]
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.foodsSelectedKey.filter((key) =>
{
for (let i=0; i<foodFilter.length;i++){
if(foodFilter[i].name===key.name)
return true
}
return false;
}
);
return matched;
};
The Output is filtered array, in this case, of one element only:
[{
id: 1
name: "chicken"
}]
In order to check the output - run console.log(findMatches()). Here is the CodeSandbox of the solution. (check console at right bottom)
var abc: [[String: Int ]] =
[["a", 0, "b": 0, "c" : 1]]
In the above example, I need a logic where I will check whether the array of dictionary has any element(value) which is greater than 1.
In my project I am navigating user to the next screen, if the array of dictionary contains at least one element which is greater than 1.
There is a typo in your code example, but you can find the value with
func ifContains(arr: [[String: Int ]], value: Int) -> Bool {
for dict in arr {
return dict.values.filter { $0 > 1 }.count > 0
}
return false
}
print(ifContains(arr: abc, value: 1))
This should do the trick:
let containsNonZeroValue = array.contains(where: { aSubDict in
return aSubDict.contains { (key: String, value: Int) -> Bool in
return value > 1
}
})
We check the different aSubDict if they contains a dictionary value superior to 1.
We could have used filter(), map(), flatMap(), etc, but contains() has the advantage of stopping once a value has been found. So if you have a big array, and 2 at the 1 index, it won't iterate over the rest of the array.
In a more concatenated way if you know how to use closures and their arguments:
let containsNonZeroValue = array.contains(where: { $0.contains { $0.value > 1 } })
As suggested by #Leo Dabus in the comments, instead of iterating all the values of the sub dictionary, we can get all the values (aSubDict.values), and check if one of them respects the constraint.
let containsNonZeroValue = array.contains(where: { aSubDict in
return aSubDict.values.contains(where: { $0 > 1 })
})
In the shorter way:
let containsNonZeroValue = array.contains(where: { $0.values.contains(where: { $0 > 1 }) })
I have two arrays one with field names and the other array is having a list of arrays where each array corresponds to row in table.How can i use these two arrays to create a list of JSON Objects. Is there any in built function. I am able to acheive this using map/reduce/ for -loop but this is impacting the performance if the second array is having more rows as we have traverse through each row.
I hope the following explains the use case better. Please share the sample code if possible.
Arr1=[field1,field2];
Arr2=[[1,2],[3,4],[5,6]];
Expected Output:
[
{
field1 :1 ,
field2: 2
},
{
field1 :3 ,
field2: 4
},
{
field1 :5 ,
field2: 6
}
]
You can use Array.map to map the elements
const mapFields = (arr1, arr2) => {
const mappedArray = arr2.map((el) => {
const mappedArrayEl = [];
el.forEach((value, i) => {
if (arr1.length < (i+1)) return;
mappedArrayEl[arr1[i]] = value;
});
return mappedArrayEl;
});
return mappedArray;
}
const Arr1 = ["field1","field2"];
const Arr2 = [[1,2],[3,4],[5,6]];
console.log(mapFields(Arr1, Arr2));
If you have an array of hashes such as:
t = [{'pies' => 1}, {'burgers' => 1}, {'chips' => 1}]
what would be an efficient and readable way to add 1 to the value of a hash that has a particular key such as 'pies'?
Here's one way to increment the value(s) of an array's hashes based on a desired key:
t = [{ 'pies' => 1 }, { 'burgers' => 1 }, { 'chips' => 1 }]
t.each { |hash| hash['pies'] += 1 if hash.key?('pies') }
# => [{"pies"=>2}, {"burgers"=>1}, {"chips"=>1}]
Hope this helps!
If you know there's only one hash that could take the key 'pies' then you can use find and increase the value it has, like:
array = [{ 'pies' => 1 }, { 'burgers' => 1 }, { 'chips' => 1 }]
pies_hash = array.find { |hash| hash['pies'] }
pies_hash['pies'] += 1
p array
# [{"pies"=>2}, {"burgers"=>1}, {"chips"=>1}]
Enumerable#find will try to find the element that satisfies the block and stops the iteration when it returns true.
You're using the wrong data structure. I recommend using a Hash.
Each item on your menu can only have one count (or sale), that is each item is unique. This can be modelled with a hash with unique keys (the items) and their corresponding values (the counts).
t = {'pies' => 1, 'burgers' => 1, 'chips' => 1}
Then we can access keys and add to the count:
t['pies'] += 1
t #=> t = {'pies' => 2, 'burgers' => 1, 'chips' => 1}
I am trying to display exactly how many of an array variable I have, not just the items in the array, but one of the 'tags' assigned to it.
$scope.products = [
{
too: 'xxx-xxx-xxx',
foo: 'xxx',
bar: 'xxx-xxx',
}
}
];
When I try to list the length of one of the 'tags' for example "Foo".
Using {{foo.length}} will not work.
I would want my HTML to look something like this:
Menu 1 (1) <--- With this being the "foo" value.
*The foo value will change based on the amount of 'items' i have in my array, so if I had an array like this:
$scope.products = [
{
too: 'xxx-xxx-xxx',
foo: 'xxx',
bar: 'xxx-xxx',
}
{
too: 'yyy-yyy-yyy',
foo: 'yyy',
bar: 'yyy-yyy',
}
}
];
the HTML would reflect that I now have '2' values of 'foo', so it would say
Menu 1 (2), and so on and so forth.. How can I accomplish this?
You can write a javascript function and just call it. (updated to only count unique foos)
$scope.countUniqueFoos = function () {
var uniqueFoos = []; //you could also keep this as a $scope variable if needed
$scope.products.forEach( function (product) {
if (product.hasOwnProperty('foo') && uniqueFoos.indexOf(product.foo) == -1) {
uniqueFoos.push(product.foo);
}
});
return uniqueFoos.length;
};
And in the HTML:
<div>NumFoos: {{countUniqueFoos()}}</div>