I am looking for a way to search an array to see if a value is present that starts with the search term.
const array1 = ['abc','xyz'];
So a search for 'abcd' would return true on the above.
I have been playing about with includes, but that only seems to check the full value.
Also, startsWith I dont think will work as I believe that checks a string and not values in an array??
You can use the find() function which allows you to pass a custom function in parameter that will be tested on each value. This way you can use startsWith() on each value of the array as you intended to do.
Example:
const array1 = ['abc','xyz'];
function findStartWith(arg) {
return array1.find(value => {
return arg.startsWith(value);
});
}
console.log(findStartWith("hello")); // undefined
console.log(findStartWith("abcd")); // abc
console.log(findStartWith("xyzz")); // xyz
If you want to return true or false instead of the value, you can check if the returned value is different from undefined.
function findStartWith(arg) {
return !!array1.find(value => {
return arg.startsWith(value);
}) !== undefined;
}
The same snippet with a boolean:
const array1 = ['abc','xyz'];
function findStartWith(arg) {
return array1.find(value => {
return arg.startsWith(value);
}) !== undefined;
}
console.log(findStartWith("hello")); // false
console.log(findStartWith("abcd")); // true
console.log(findStartWith("xyzz")); // true
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
Yet, another question about JSON-like Object literals.
the object that I work with has the following structure:
let family ={
"id":"someId",
"participants":[
{
"name":"Q",
"sex":"m",
"age":23,
"occupations":[
{
"jobId":"some ID"
"finished": true,
"start": dateTime,
"end":dateTime,
"skills":[
{
"name":"welding"
},
{
"name":"concrete mixing"
},
]
},
{
"jobId": "someId",
"finished": false,
"skills":[
{
"name":"power lifting"
},
{
"name":"swimming"
},
{
}
]
},
{"OTHER Participant"},
{"OTHER Participant"}
]
}
It is for the sake of example.
when I receive data, every literal object is going to be unique so there is no "schema" that I can create and refer to based on the type, for example.
And I need to find the unique objects on the 2nd, 3rd, 4th etc levels.IF they exist
My take on this:
Every time I would try to use something either like :
let personIneed; //to save him later;
let part = family.participants;
for (const xx of part){
let partJobs =xx.occupations;
for (const xxx of partJobs){
if(xxx.end && xxx.finished == true){
let partJobSkills = xxx.skills;
let isSkillPresent =false; //to change to true once skill iteration is finished
for (const xxxx of partJobSkills){
if(xxxx.name ==="concrete mixing"){
isSkillPresent =true;
}
}
//check if skill's there and save the participant
if(isSkillPresent){
personIneed = xx;
return;
}
}
}
}
Which is very bulky and if i have to build a function like that for every set of criteria... well I'd rather build a guillotine. It also looks a little bit like a callback Hell to me (the way it cascades and only) :)
Either when the search is only at the high level,
let part = family.participants;
let man = part.find (p=>p.sex==="m");
Which would only return me the first person to match the criteria. which is not ideal.
I would like to build a generalized function that will be able to go through the Object literals finding the nested objects that match my criteria. The criteria should be passed as parameters of the function. Function should also consider that there can be several nested objects with the same keys ( for example one person can be a Builder on many different jobs) or there can be in fact none of the objects that match the criteria.
The ultimate goal is somehow to make all the nested objects easily accessible when the object is found. (for example when we found a person who has worked as a builder and who has finished his contract, we return this object but if i need to find the start and end of his working period, I need to go through all the nested objects again and it becomes hell again)
Please note that some arrays will simply not exist and some will have one value.
From your comments, it sounds like you're looking for a generalized way to loop through nested objects and arrays. You'd do that with recursion. If you want to make it possible to collect information, or to stop the operation, in different ways for different places you use it, you can pass in a callback function.
Here's an example:
// A version of `Object.prototype.hasOwnProperty` that we can call with
// any object and key. For arrays, we use this to check for empty slots
// (holes in a sparse arary). For non-array objects, we use this to skip
// inherited properties; in the not-array path below, you could remove
// the `hasOwn` check if you wanted to process inherited properties (but
// probably best to keept it for the array path).
const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
// The deep search function
function deepSearch(obj, callback) {
if (Array.isArray(obj)) {
// It's an array, loop through it
for (let index = 0, len = obj.length; index < len; ++index) {
// Is there an entry at this index?
if (hasOwn(obj, index)) {
// Yes, get its value
const value = obj[index];
// Call the callback
if (callback(obj, index, value)) {
// Callback returned a truthy value, stop here and
// return true
return true;
}
// Is this value an object?
if (value && typeof value === "object") {
// Yes, recurse
if (deepSearch(value, callback)) {
// Recursion found it, stop here
return true;
}
}
}
}
} else {
// It's not an array, loop through the object keys
for (const key in obj) {
// Is this an "own" property (not inherited)?
if (hasOwn(obj, key)) {
// Yes, get its value
const value = obj[key];
// Callback the callback
if (callback(obj, key, value)) {
// Callback returned a truthy value, stop here and
// return true
return true;
}
// Is this value an object?
if (value && typeof value === "object") {
// Yes, recurse
if (deepSearch(value, callback)) {
// Recursion found it, stop here
return true;
}
}
}
}
}
// Not found, return false
return false;
}
Here's a live version using a callback to find something specific and stop the iteration:
const example = {
first1: "value of first1",
first2: {
second1: "value of second1",
second2: [
{
third11: "value of third11",
third12: {
fourth11: "value of fourth11",
},
},
{
third21: "value of third21",
third22: {
fourth21: "value of fourth21",
},
},
],
},
};
// A version of `Object.prototype.hasOwnProperty` that we can call with
// any object and key. For arrays, we use this to check for empty slots
// (holes in a sparse arary). For non-array objects, we use this to skip
// inherited properties; in the not-array path below, you could remove
// the `hasOwn` check if you wanted to process inherited properties (but
// probably best to keept it for the array path).
const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
// The deep search function
function deepSearch(obj, callback) {
if (Array.isArray(obj)) {
// It's an array, loop through it
for (let index = 0, len = obj.length; index < len; ++index) {
// Is there an entry at this index?
if (hasOwn(obj, index)) {
// Yes, get its value
const value = obj[index];
// Call the callback
if (callback(obj, index, value)) {
// Callback returned a truthy value, stop here and
// return true
return true;
}
// Is this value an object?
if (value && typeof value === "object") {
// Yes, recurse
if (deepSearch(value, callback)) {
// Recursion found it, stop here
return true;
}
}
}
}
} else {
// It's not an array, loop through the object keys
for (const key in obj) {
// Is this an "own" property (not inherited)?
if (hasOwn(obj, key)) {
// Yes, get its value
const value = obj[key];
// Callback the callback
if (callback(obj, key, value)) {
// Callback returned a truthy value, stop here and
// return true
return true;
}
// Is this value an object?
if (value && typeof value === "object") {
// Yes, recurse
if (deepSearch(value, callback)) {
// Recursion found it, stop here
return true;
}
}
}
}
}
// Not found, return false
return false;
}
deepSearch(example, (obj, key, value) => {
console.log(`Looking at ${key}, value: ${Array.isArray(value) ? "(array)" : value && typeof value === "object" ? "(object)" : JSON.stringify(value)}`);
if (key === "third21") {
console.log(`*** Found third21, value = ${value}`);
return true;
}
});
.as-console-wrapper {
max-height: 100% !important;
}
I have a data response that responds with different objects in an array.
I have tried a variety of different methods to determine if the key 'name' exists including:
const hasName = array.forEach(item => "name" in item )
const hasName = array.forEach(item => Object.keys(item).includes('name') )
const hasName = array[0].hasOwnProperty("name") ? true : null
const hasName = array => array.some(x => x.some(({ name }) => name));
// lodash 'has' method
const hasName = has(array, 'name')
Array1 returns objects like:
[
{
name: 'cool name'
}
]
Array2 returns objects like:
[
{
group: 'cool group'
}
]
All of the methods I tried have either returned undefined or nothing at all and I'm completely at a loss for why. I have scoured Stack Overflow and the internet trying to get a better direction or an answer but I haven't been able to find anything.
You're not returning anything from some of your calls on the array. forEach for example runs a callback, and always returns undefined see docs. Your code just isn't working because you're using the functions incorrectly.
The code below filters your array to get the elements with a name property, then counts them to see whether one or more exists, which results in a true or false being stored in the hasName variable.
let myArr = [
{
name: 'cool name'
}
]
const hasName =
myArr
.filter(a => a.hasOwnProperty("name")) // filter for elements in the array which have a name property
.length // get the number of filtered elements
> 0 // check whether the number of elements in array with name prop is more than 0
console.log(hasName)
If you are sure that the "response" is fully received before the check, THEN
Your latest variant of the check can be implemented as follows:
array.some(obj => (obj.name !== undefined)); // fast, but not define .name if it is "undefined"
array.some(obj => obj.hasOwnProperty("name")); // slower, but will define .name with any value
Your solutions are generally correct, but it looks like you're a little confused,
Array.forEach always returns "undefined":
array.forEach(obj => {
console.log("name" in obj); // true for 1st array
console.log("group" in obj); // true for 2nd array
}); // return "undefined"
array[0].hasOwnProperty() works fine, and can't return "undefined" at all.
console.log(
array[0].hasOwnProperty("name") ? true : null; // return ("true" for the 1st array) AND ("null" for the 2nd)
);
When you used the Lodash, maybe you forgot to point to the object index?
_.has(array[0], 'name'); // return ("true" for the 1st array) AND ("false" for the 2nd)
Try a for loop
for (var i = 0; i < array.length; i++) {
if (array[i].hasOwnProperty('name')) {
console.log(array[i].name); //do something here.
break;
}
}
I have an array with name validationValueIdValues so when user clicks on the input state ie. validationIdValue takes the value of individual input box. Now one user select on of option that is either Yes or No. The function creates an obj with key name equal to state, validationIdValue and value equal to users selection in short creates an obj like this
{08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b: "NO"}
Then this object is pushed to validationValueIdValues variable. Now problem arises when user select same box and changes select value from NO to YES
{08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b: "YES"}
Then this object is pushed to the validationValueIdValues variable without checking if previous same obj with key exist or not and if exist then delete that obj from array. I am using following code for this purpose but some how duplicate obj still exist in an array.
var validationValueIdValues = [] //as global variable
if (this.state.selectedOption === "YES") {
const attribute = {};
attribute[this.state.validationIdValue] = "YES";
if (validationValueIdValues.length > 0) {
validationValueIdValues.forEach((data, index) => {
if (Object.keys(data) == this.state.validationIdValue) {
validationValueIdValues.splice(index, 1);
validationValueIdValues.push(attribute);
}
});
} else {
validationValueIdValues.push(attribute);
}
}
I have used same if statement for this.state.selectedOption === "NO"
You will need to check all keys in the array to find the matching value. You don't need the code to be repeated for "YES" or "NO" as you mentioned. Something like this is generic enough to handle it
const validationValueIdValues = [] //as global variable
const addOrUpdateValidationValues = (newValidationValue) => {
if(!newValidationValue) {
return;
}
const keyOfNewValue = Object.keys(newValidationValue)[0]
let added = false
// loop through all values
for(const validationValue of validationValueIdValues) {
const keyOfCurrentValue = Object.keys(validationValue)[0]
if(keyOfNewValue === keyOfCurrentValue) {
// found that kind of key then just replace the value
added = true
validationValue[keyOfCurrentValue] = newValidationValue[keyOfNewValue]
}
}
// not added push
if(!added) {
validationValueIdValues.push(newValidationValue)
}
}
// ...
// when you have the select or what ever event
// just call
addOrUpdateValidationValues(this.state.selectedOption)
Use .findIndex() with .some() to see if the value exists in the array, if exists update the value or push the new value.
const array = [{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}, {'tyhgsgsvbb': 'NO'}];
const found = array.findIndex((item) => Object.keys(item).some(key => key === 'tyhgsgsvbb'));
if (found) {
// toggle the value from yes to no, or vice versa
array[found] = array[found] === 'YES' ? 'NO' : 'YES'
} else {
array.push({newKey: 'newValue'});
}
console.log(array)
const newObject = {'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "NO"}
const array = [{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}, {'tyhgsgsvbb': 'NO'}];
const items = array.filter(item => item['08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b'])
if(allKeys.length>0) array[array.findIndex(items[0])] = newObject
else array[array.length] = newObject
You can try this!
const array=[{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"},{'08754d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}];
let newValue = {'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"};
const index = array.findIndex(e=>Object.keys(e).indexOf(Object.keys(newValue)[0])>-1);
if(index > -1){
array.splice(index,1,newValue); //Replacing the value
} else {
array.push(newValue);
}
'in' can be used to check for the key in array
// if key not in array then add to array
if ( !( 'mydata' in myArray) ) {
myArray['mydata'] = 99;
}
I need to evaluate if an object is empty.
For example suppose I have an object:
var home = ....; // this is an object and after I print it
console.log(home) // the result of this option is []
//now I need to check if a object is empty or null
if( home == null || home == undefined )
{
// I don't know specify how object is empty
}
How can I detect whether or not the above object home is null/empty?
To check for an empty array
if (!arr.length) {
// if the array is empty
}
and for an object (check that it has no keys)
if (!Object.keys(obj).length) {
// if the object is empty
}
DEMO
Only way I see so far may be ({}).toSource() === o.toSource()
Example:
var y = {a: 't'};
window.console.log(({}).toSource() === y.toSource());
delete y.a;
window.console.log(({}).toSource() === y.toSource());
EDIT : Oh, nicely found, Andy.