Cannot get/fetch keys from an array in javascript - javascript

I have an array object where there are key value pairs. I am trying to get the keys in that array using a loop but I am getting only 0. What is the problem with my code.
var strj = '{"name":"John","age":"30","cars":
[ {"type":"car", "year":"1998"},
{"type":"van", "year":"1995"}]}';
var myobj = JSON.parse(strj)
var care = myobj.cars.filter(c => c.type=='car');
Value of care
0:{type: "car", year: "1998"}
length:1
__proto__:Array(0)
Loop
for (var key in care){
if(care.hasOwnProperty(key)){
console.log(key)
}
}

care is a array type so you cannot do for (var key in care). You need to do for (var key in care[0]). This is because for (var key in care) will look for the key value in care and since it is a array it will always take 0 as a value in key(as you have only one object in array and its index is 0). That is why you got 0 in console.log.
var care =[{type: "car", year: "1998"}];
for (var key in care[0]){
if(care[0].hasOwnProperty(key)){
console.log(key)
}
}

care.forEach( ( singleCar ) => {
for ( var key in singleCar ){
console.log(key);
if( care.hasOwnProperty( key ) ){
console.log(key);
}
}
})
forEach will give you all the objects one by one. so you can check them.

As others have solved the issue, might i make a suggestion - Object.keys () gives an array of the keys for a given object. Since you are getting your filtered object and simply want its keys - the following will achieve that. Note that this is only using the code after you have filtered the original and have gained the "care" object.
As an aside, note that object.values() will give you an array of the values in a given object and object.entries() will give you arrays of the key / value pairing.
var care = {type: "car", year: "1998"};
var keys = Object.keys(care)
console.log(keys) // gives ["type","year"]

filter() method returns a Array of matches.
var care = myobj.cars.filter(c => c.type=='car'); // So, this returns an array.
care.forEach(element => {
console.log(Object.keys(element)); //Prints keys of each element
});

Well actually there is no problem in your code at all. But you just misunderstood the use of javascript filter. Javascript filter() creates new array that's why you are getting 0 as key. If you want to get only one matching element then find() is what you should use.
var strj = '{"name":"John","age":"30","cars":[{"type":"car", "year":"1998"},{"type":"van", "year":"1995"}]}';
var myobj = JSON.parse(strj)
var care = myobj.cars.filter(c => c.type == 'car'); // returns array
var care = myobj.cars.find(c => c.type == 'car'); // returns first matching object
var care = myobj.cars.findIndex(c => c.type == 'car'); // returns first matching index
Javascript filter() method => Read Here
Javascript find() => Read Here
Javascript findIndex() method => Read Here

Related

Getting object from array of objects matching values inside and array of dates with lodash

i have an array of obejcts that has this structure
let events = [ {
"initDate": "2019-11-20",
"finalDate": "2019-11-22",
"intermediateDates": [
"2019-11-20",
"2019-11-21"
],
"priority": 1
},....]
So, i'm trying to get the object that matches from a given array of dates for example :
let filteredDays = [
"2019-11-20",
"2019-11-21",
"2019-11-22"
]
i'm trying with lodash like this:
let eventsFound= [];
let intersection = _.map( this.events,function(value){
let inter = _.intersection(value.intermediateDates,filteredDates);
console.log(inter);
if(inter != []){
foundEvents.push(value);
return value;
}else{
return false;
}
});
when i console log inter i get the first array with values then the next arrays are empty but it keeps pushing all the events into the foundEvents Array and the returned array is the same as the events array.
You're comparing two arrays using !=. In javascript [] != [] is always true. To check if an array is empty, use length property like arr.length == 0.
Use filter instead of using map like a forEach.
To check existance use some/includes combo instead of looking for intersections.
So, filter events that some of its intermediateDates are included in filteredDates:
let eventsFound = _.filter(this.events, event =>
_.some(event.intermediateDates, date =>
_.includes(filteredDates, date)
)
);
The same using native functions:
let eventsFound = this.events.filter(event =>
event.intermediateDates.some(date =>
filteredDates.includes(date)
)
);

How to check if the key exist in json array?

I have a json object, the structure of which is given below. I try to find if the key (for eg: 1 & 2) exist or not by myArray.includes('1') but it doesn't work. Is looping through the array the only way to check if attribute exist or not?
[{"1": [{}]},{"2": [{}]}]
The way to check if an object with a particular property exists or not would be to filter the objects by verifying if they have given property or not.
To check if an object contains a property you could use Array.prototype.includes on the list of keys obtained through Object.keys. Here's an example:
var data = [
{"1" : []},
{"2" : []}
];
// Count of objects containing a given key.
console.log(data.filter(t => Object.keys(t).includes("1")).length);
console.log(data.filter(t => Object.keys(t).includes("2")).length);
console.log(data.filter(t => Object.keys(t).includes("3")).length);
You have to loop through all of the elements in the Array and check if the key exists in each of those Objects.
arr.some(e => e.hasOwnProperty('1'));
You can use Array.some() which tests whether at least one element in the array passes the test.
const has1 = myArray.some(obj => obj.hasOwnProperty(“1”)); // Returns a boolean
const has2 = myArray.some(obj => obj.hasOwnProperty(“2”)); // Returns a boolean
You can use use some() and Object.prototype.hasOwnProperty()
The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
let arr = [{
"1":[{}],
"2":[{}]
}]
let checkOne = arr.some(x => x.hasOwnProperty('1'));
let checkThree = arr.some(x => x.hasOwnProperty('3'));
console.log(checkOne) //true
console.log(checkThree) //false
You can try forEach to loop the keys of object and check if yours is there.
var obj = yourobject;
var mykey = 0;
Object.keys(obj).forEach(function(k){
if(k == mykey){
...
}
});

How to edit value of an object using the reference?

I have a big object array persons
persons = [{name:'john1'}, {name:'john2'},...]
I iterated the array and found the object I am interested to edit
objectToEdit = persons .find((person)=>person.name==='john1')
Now I created an edited object in immutable way (someOtherPerson = {name:'johnxx'})
objectFinal = {...objectToEdit, someOtherPerson}
Now I want to replace this objectFinal with objectToEdit in persons array, without having to traverse the array again. But doing objectToEdit =objectFinal , will just assign objectToEdited's reference to objectToEdit , without making any change in the persons array
Is there a clean way to achieve this without traversing the array?
Edit:
In this example, the object in persons jave just one key (i.e, name). This is to make question minimal. In my project, I have more than 30 keys.
If you want to edit an object in a list,in place, use Array.prototype.some
var persons = [{
name: 'john1'
}, {
name: 'jack5'
}]
var someOtherPerson = {
name: 'johnxx'
}
persons.some(function(person) {
// if condition, edit and return true
if (person.name === 'john1') {
// use Object.keys to copy properties
Object.keys(someOtherPerson).forEach(function(key) {
person[key] = someOtherPerson[key]
})
// or use assign to merge 2 objects
Object.assign(person, someOtherPerson);
return true // stops iteration
}
})
console.log(JSON.stringify(persons))
If you want to avoid mutating the objects in the original array, you might use .findIndex instead, and reassign the item in the array at that index:
const persons = [{name:'john1'}, {name:'john2'}];
const objectToEditIndex = persons.findIndex((person) => person.name === 'john1');
const someOtherPerson = {name:"johnxx"};
persons[objectToEditIndex] = {
...persons[objectToEditIndex],
...someOtherPerson
};
console.log(persons);
Doing this:
objectFinal = {...objectToEdit, someOtherPerson}
you lose the reference to the original objectToEdit object. To edit it, you can do
`objectToEdit.value = otherValue`.
PS: Having said that, you only lose reference to the first level object. If that object, contains another object or array, you have reference to it:
objectFinal.innerObject.value = otherValue;
{name:'john1'} should be replace with {name:"johnxx"} in persons
Reassign persons to the persons-array mapped with the new value:
let persons = [{name:'john1'}, {name:'john2'}];
persons = persons.map( v => v.name === "john1" ? {name: "johnxx"} : v );
console.log(persons);
Or, if you're worried about performance, use Array.splice in combination with Array.findIndex
The findIndex method executes the callback function once for every
array index 0..length-1 (inclusive) in the array until it finds one
where callback returns a truthy value (a value that coerces to true).
If such an element is found, findIndex immediately returns the index
for that iteration.
let persons = [{name:'john1'}, {name:'john2'}];
persons.splice(persons.findIndex( v => v.name==="john1" ), 1, {name:'johnxx'});
console.log(persons);
Or use a utility method (snippet for a large array (1,000,000 elements) and with performance timer)
// replacer method
const replace = (obj, [key, value], replacement) => {
obj.splice(persons.findIndex( v => v[key] === value ), 1, replacement);
return obj;
}
// create a large array (this may take some extra time)
let persons = Array.from({length: 1000000}).map(v =>
({name: Math.floor(100000 + Math.random() * 1000000000).toString(16)}) );
// pick an entry
const someEntry = Math.floor(persons.length * Math.random());
const entry = Object.entries(persons[someEntry])[0];
console.log("before:", persons[someEntry]);
const t = performance.now();
// replacement call here
console.log("after:", replace(persons, entry, {name: "johnxx"})[someEntry]);
console.log("replacement took:", `${((performance.now() - t)/1000).toFixed(3)} sec`);

get key and value of array via underscore each

I would like to loop through an array and get the key and value of it. This is what I'm doing, but I don't get any output. What am I doing wrong?
let regexes = [];
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.each(regexes, function(regex, key) {
console.log(regex, key);
});
You are using array and adding a property to it which is not valid .Use object for it
let regexes = {};
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.each(regexes, function(regex, key) {
console.log(regex, key);
});
_.each iterates through the indices of the array. You are adding a non-numeric property to the array object. Your array is empty and _.each callback is not executed. It seems you want to use a regular object ({}) and not an array:
let regexes = {};
Now _.each should iterate through the object own (by using hasOwnProperty method) properties.
You are assigning a property to the array. Lodash is attempting to iterate through the numeric indices of the array, but there are none. Change the array to an object and Lodash will iterate through its enumerable properties:
let regexes = {};
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.forEach(regexes, function(regex, key) {
console.log(regex, key);
});
Alternatively, if using an array is necessary, simply push the value onto it:
let regexes = [];
regexes.push(/([^.]+)[.\s]*/g);
_.forEach(regexes, function(regex, i) {
console.log(regex, i);
});

JavaScript foreach loop on an associative array object

Why is my for for-each loop not iterating over my JavaScript associative array object?
// Defining an array
var array = [];
// Assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";
// Expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
jQuery each() could be helpful: https://api.jquery.com/jQuery.each/
The .length property only tracks properties with numeric indexes (keys). You're using strings for keys.
You can do this:
var arr_jq_TabContents = {}; // no need for an array
arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;
for (var key in arr_jq_TabContents) {
console.log(arr_jq_TabContents[key]);
}
To be safe, it's a good idea in loops like that to make sure that none of the properties are unexpected results of inheritance:
for (var key in arr_jq_TabContents) {
if (arr_jq_TabContents.hasOwnProperty(key))
console.log(arr_jq_TabContents[key]);
}
edit — it's probably a good idea now to note that the Object.keys() function is available on modern browsers and in Node etc. That function returns the "own" keys of an object, as an array:
Object.keys(arr_jq_TabContents).forEach(function(key, index) {
console.log(this[key]);
}, arr_jq_TabContents);
The callback function passed to .forEach() is called with each key and the key's index in the array returned by Object.keys(). It's also passed the array through which the function is iterating, but that array is not really useful to us; we need the original object. That can be accessed directly by name, but (in my opinion) it's a little nicer to pass it explicitly, which is done by passing a second argument to .forEach() — the original object — which will be bound as this inside the callback. (Just saw that this was noted in a comment below.)
This is very simple approach. The advantage is you can get keys as well:
for (var key in array) {
var value = array[key];
console.log(key, value);
}
For ES6:
array.forEach(value => {
console.log(value)
})
For ES6 (if you want the value, index and the array itself):
array.forEach((value, index, self) => {
console.log(value, index, self)
})
If Node.js or the browser support Object.entries(), it can be used as an alternative to using Object.keys() (Pointy's answer).
const h = {
a: 1,
b: 2
};
Object.entries(h).forEach(([key, value]) => console.log(value));
// logs 1, 2
In this example, forEach uses destructuring assignment of an array.
There are some straightforward examples already, but I notice from how you've worded your question that you probably come from a PHP background, and you're expecting JavaScript to work the same way -- it does not. A PHP array is very different from a JavaScript Array.
In PHP, an associative array can do most of what a numerically-indexed array can (the array_* functions work, you can count() it, etc.). You simply create an array and start assigning to string indexes instead of numeric.
In JavaScript, everything is an object (except for primitives: string, numeric, boolean), and arrays are a certain implementation that lets you have numeric indexes. Anything pushed to an array will affect its length, and can be iterated over using Array methods (map, forEach, reduce, filter, find, etc.) However, because everything is an object, you're always free to simply assign properties, because that's something you do to any object. Square-bracket notation is simply another way to access a property, so in your case:
array['Main'] = 'Main Page';
is actually equivalent to:
array.Main = 'Main Page';
From your description, my guess is that you want an 'associative array', but for JavaScript, this is a simple case of using an object as a hashmap. Also, I know it's an example, but avoid non-meaningful names that only describe the variable type (e.g. array), and name based on what it should contain (e.g. pages). Simple objects don't have many good direct ways to iterate, so often we'll turn then into arrays first using Object methods (Object.keys in this case -- there's also entries and values being added to some browsers right now) which we can loop.
// Assigning values to corresponding keys
const pages = {
Main: 'Main page',
Guide: 'Guide page',
Articles: 'Articles page',
Forum: 'Forum board',
};
Object.keys(pages).forEach((page) => console.log(page));
arr_jq_TabContents[key] sees the array as an 0-index form.
Here is a simple way to use an associative array as a generic Object type:
Object.prototype.forEach = function(cb){
if(this instanceof Array) return this.forEach(cb);
let self = this;
Object.getOwnPropertyNames(this).forEach(
(k)=>{ cb.call(self, self[k], k); }
);
};
Object({a:1,b:2,c:3}).forEach((value, key)=>{
console.log(`key/value pair: ${key}/${value}`);
});
This is (essentially) incorrect in most cases:
var array = [];
array["Main"] = "Main page";
That creates a non-element property on the array with the name Main. Although arrays are objects, normally you don't want to create non-element properties on them.
If you want to index into array by those names, typically you'd use a Map or a plain object, not an array.
With a Map (ES2015+), which I'll call map because I'm creative:
let map = new Map();
map.set("Main", "Main page");
you then iterate it using the iterators from its values, keys, or entries methods, for instance:
for (const value of map.values()) {
// Here, `value` will be `"Main page"`, etc.
}
Using a plain object, which I'll creatively call obj:
let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`
you'd then iterate its contents using Object.keys, Object.values, or Object.entries, for instance:
for (const value of Object.values(proches_X)) {
// Here, `value` will be `"Main page"`, etc.
}
var obj = {
no: ["no", 32],
nt: ["no", 32],
nf: ["no", 32, 90]
};
count = -1; // Which must be a static value
for (i in obj) {
count++;
if (obj.hasOwnProperty(i)) {
console.log(obj[i][count])
};
};
In this code I used the brackets method for call values in an array because it contained an array. However, briefly the idea which a variable i has a key of property and with a loop called both values of the associative array.
It is the perfect method.
You can do this:
var array = [];
// Assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";
array.forEach(value => {
console.log(value)
})
It seems like almost every answer is not what was asked at the very first place.
It's seems bit off that foreach-loop does not work. and simple for-loop will not work as well because length property will be zero in case of associative arrays(one of the fallback). but for-in do the thing for associative array
// Defining an array
var array = [];
// Assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";
// Expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var index in array) {
console.log(index,array[index]);
}

Categories

Resources