Determine if nested array within object have values - javascript

I have an object that looks like this:
steps: {
'36793745-4c52-42d2-91a5-dcdc9de2e8fa': [],
'b23d8770-806f-44a9-aa2e-a21dd68f7977': [],
'33571d58-b833-4a7d-a1a1-ec96366cb74a': [],
'b1499917-7f82-49e5-9708-6237340a9610': []
}
Each array within that object can be an array of strings.
I'd like to check if any of those arrays have an item, if they do, I like to return true.
I do not care about checking any after, as soon as one returns true, I am happy.
I tried something like Object.keys(steps).map(step => steps[step].length > 0) but this returns an array of true or false [false, false, false, false]
I then tried Object.keys(steps).filter(step => steps[step].length > 0) but this returns an array of the item keys that do have a value.
I know at this point I could simply check the length of the result but I was wondering if there is a better way to achieve this.
This object could potentially grow in size considerably, so I was hoping for some sort of early exit as soon as I get a true

You could use the values and a check for the length of the array.
var hasItems = Object.values(steps).some(array => array.length);

Use some.
It can be used to check if at least one element in the array passes a condition or not. Like Array.Filter, it accepts a test function where it loops through the source array’s element.
It returns true if any one of the element passes the test condition. If all the elements fails on the test function, it returns false. it short circuits the loop as soon as one of element passes the test function.
const stepHasProp = Object.values(steps).some(array => array.length)

Related

How can I check if javascript array already contains a specific array

I learn Javascript and read and understand how the includes works to test if a value exists in an array.
My problem comes when I have an Array of items that look like this this:
state = { focused: null, files: [] };:
The image show this here:
When I add a new newFile and it's the same it should not add it ok but the evaluation,
if (newFile && !files.includes(newFile)) {.. always say false so how to test for this do I have to test on individual values inside newFiles?
Array.includes will not do a deep comparison between object, only a shallow one comparing references. This way even objects that have same values they would fail on test because they have different references.
In your case you could compare id, which should be unique for each object. You can use Array.every that checks if all values pass in the test. This way you want to check that every file id doesn't match newFile id:
if (newFile && files.every(({id}) => newFile.id !== id))
Array.includes does reference comparison for Array or Object, so instead you can use Array.filter
if (newFile && newFile.filter(e => { /*Comparison logic */ }).length > 0)

Nested array filter() functions in typescript - always returns true?

I have a very simple function that tests if two lines are intersecting. The intersection function itself works as expected, but when I attempt to use it in nested filter() functions, the outer filter function always returns true:
const intersectingLines: Line[] = poly1Lines.filter(poly1Line => {
return poly2Lines.filter(poly2Line => {
return (isIntersecting(poly1Line, poly2Line));
});
});
I am nesting the filter functions so that I run through all lines in the first polygon testing if it intersects any line in the second (similar to looping over the second array on each iteration of an outer loop over the first array).
I suspected this was happening because the second filter is never returning falsy, so I checked directly for the length of the filtered array, which works as below:
const intersectingLines: Line[] = poly1Lines.filter(poly1Line => {
const filteredLines = poly2Lines.filter(poly2Line => {
return (isIntersecting(poly1Line, poly2Line));
});
return (filteredLines.length > 0)
});
This feels hacky and less readable than simply nesting the returns of the filters. I'm convinced that I'm nesting the filter functions wrong, but I'm finding little documentation on how to do this. Is there a better way to do this than checking the length of the second filtered array?
Indeed, filter always returns an array, which - as an object - is truthy.
The proper solution is not to use .filter(…).length to check whether some of the array elements match a predicate, but to use .some(…):
const intersectingLines: Line[] = poly1Lines.filter(poly1Line =>
poly2Lines.some(poly2Line =>
isIntersecting(poly1Line, poly2Line)
)
);

How to check if object is empty using lodash _isEmpty?

i have map function that is returning empty object for the array now if i check array _isEmpty this condition should satisfy but its not getting into if statement. Any idea what is implemented wrong or better approach ?
main.js
const validateResponse = _.map(drugs ,validateValues);
now validateResponse returns [{}] and it should satisfy condition
if (_.isEmpty(validateResponse)) {
throw invalidPriceError;
}
As per the lodash documentation here:
Array-like values such as arguments objects, arrays, buffers, strings, or jQuery-like collections are considered empty if they have a length of 0. Similarly, maps and sets are considered empty if they have a size of 0.
[{}].length happens to be 1. A cabbage-in-a-box, if you will. An array with one empty object. Hence, isEmpty evaluates to false. [].length, on the other hand, equals 0.
You'll have to compact out the internals or check one level deeper:
if (!validateResponse.filter(r => !_.isEmpty(r)).length){
throw invalidPriceError;
}
There might be a handful of other cases you want to cover, like empty array, or an array of two empty objects, etc. Variations on the following should do what you need...
let array = [{}];
// contains any empty object
console.log(_.some(array, _.isEmpty))
// contains only empty objects
console.log(_.every(array, _.isEmpty))
// contains exactly one empty object
console.log(_.every(array, _.isEmpty) && array.length == 1)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.js"></script>
If you just want to check if there is a single array with a single empty object [{}] you can use _.isEqual:
const hasEmpty = arr => _.isEqual(arr, [{}])
console.log(hasEmpty([])) // false
console.log(hasEmpty([{}])) // true
console.log(hasEmpty([{}, {}])) // false
console.log(hasEmpty([{ a: 1 }])) // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Since the array isn't actually empty, but what you're truly checking for is "does the array have exactly one value, and is that single value an empty object?", you could just do this check:
if (validateResponse.length === 1 && _.isEmpty(validateResponse[0])) {
throw invalidPriceError;
}

Filter an array of strings from another array of strings in javascript (this is not a duplicate)

I have an array: ['Bobby', 'John', 'Sam'], and another simply ['Bobby', 'John']. I want to filter The second array from the first, leaving only Sam. I'm trying to achieve this with filter.
Use Array#filtermethod with Array#indexOf method:
var a = ['Bobby', 'John', 'Sam'],
b = ['Bobby', 'John'];
var res = a.filter(function(v) {
return b.indexOf(v) == -1;
// or in latest browser
// return !b.includes(v);
})
console.log(res);
This works because Array#filter takes a callback that is a predicate, and filters elements of an array based on that callback. If the callback returns true, the element is kept, otherwise it is filtered out. Per the documentation:
callback
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise
In the snippet above, v holds the value for the current value being processed in the array. The code then goes through the a array, returning true or false based on if that element (v) appears in b, with Array#indexOf.
Since Array#indexOf returns -1 if the element does not exist in the array, the callback checks to see if v does not exist in b. If it does not, filter it out, thus giving the desired result.

Filter an array of numbers where 0 is a valid input

I'm trying to filter a list of elements by their index, and it is possible that the first item is the item I want to get.
It seems that trying to filter a 0 using
arr.filter(function(f) {
if (Number.isInteger(f)) return f;
});
does not work. Though Number.isInteger(0) is true.
Here's a fiddle I've created to show an example. The array filtered should have two values, not one.
https://jsfiddle.net/yb0nyek8/1/
because 0 is a falsey value in javascript returning f where f is 0 will essentially be returning false.
arr.filter(Number.isInteger)
should be all you need since filter wants a function that returns true or false anyways.
The statement within your .filter() function is returning 3, 0, undefined, which in the truthy/falsey universe is true, false, false. This means the return from the .filter() function is [3].
If you want to return all integer values use the following:
var a1 = arr.filter(function(f) {
return Number.isInteger(f);
});
This will return [3,0] from the .filter() function.
Array.filter runs a given function on each item in the array, and decides whether to keep it or toss it based on whether the function returns true or false. There's no need to return the number on your own.
By returning the number itself, you end up returning the number 0, which array.filter perceives as "false", causing it to not include it.
Since Number.isInteger() returns a true or false on its own, just use it by itself.
arr.filter(function (f){
Number.isInteger(f);
})

Categories