Checking if a Javascript object contains the same key/value Lodash - javascript

Can't figure out how to find an equal key:value in the array consisted of objects.
I have an Array with the objects that look like this
[{
0:false,
1:false,
2:false,
3:true,
4:false,
5:false
},{
0:false,
1:false,
2:false,
3:true,
4:false,
5:false
},{
0:false,
1:false,
2:false,
3:true,
4:false,
5:false
}]
I need to iterate this Array with objects and if all Objects get the same key with true value (In the example above all objects have the same key:3 with value: true) and then I need to catch this key (position).
What is the best solution for this? I also use Lodash so maybe with this library it easy to get what I want or maybe to use plain javascript. It's no matter how to get it, just need a right solution.

Use _.findKey and _.every
var arr = [{"0":false,"1":false,"2":false,"3":true,"4":false,"5":false},{"0":false,"1":false,"2":false,"3":true,"4":false,"5":false},{"0":false,"1":false,"2":false,"3":true,"4":false,"5":false}];
var key = _.findKey(arr[0], function(val, key) {
return val && _.every(arr, key);
});
console.log(key);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
If you're using ES6, you can shorten that to:
let key = _.findKey(arr[0], (v, k) => v && _.every(arr, k));
If you decide to switch to a more natural 2D array structure, use _.findIndex instead.
[
[false,false,false,true,false,false],
[false,false,false,true,false,false],
[false,false,false,true,false,false],
[false,false,false,true,false,false],
[false,false,false,true,false,false]
]

First of all, I changed the objects with the keys being the index to arrays for simplicity, because that's what an array is: just a special object with indices as keys.
You can try this. It doesn't use lodash (I'm not familiar with it, sorry), but what it does is:
Start with an array of all true values that matches the length of each object (i.e., length is six)
Loop through each object and each property of each object.
If it is false, then the value of that index is false. If it is true, then the index will be true if the index is already true.
Print out the index that remains true.
You can see what I mean with the code below:
var list = [[false,false,false,true,false,false],[false,false,false,true,false,false],[false,false,false,true,false,false],[false,false,false,true,false,false],[false,false,false,true,false,false]];
var trueKeys = [true, true, true, true, true, true];
for(obj in list)
for(prop in list[obj])
trueKeys[prop] = trueKeys[prop] && list[obj][prop];
var index = trueKeys.indexOf(true);
console.log(index);

Related

Find index of object in javascript using its property name

I want to find Index of javascript array of objects using objects property name. My code is :-
const checkbox = [{'mumbai': true},{'bangalore': true},{'chennai': true},{'kolkata': true}];
How can i find index of chennai? Can i acheive using lodash?
You can use .findIndex()
const checkbox = [
{'mumbai': true},
{'bangalore': true},
{'chennai': true},
{'kolkata': true}
];
const finder = (arr, key) => arr.findIndex(o => key in o);
console.log(finder(checkbox, 'chennai'));
console.log(finder(checkbox, 'kolkata'));
console.log(finder(checkbox, 'delhi'));
checkbox.map((v,i) => Object.keys(v).indexOf("chennai") !== -1 ? i : -1).filter(v => v !== -1)[0]
Will give you the index of "chennai", replace it with any other key to get a different index.
What this does is:
Map the array to an array indicating only indices which contain objects with the wanted key
Filter only the indices which you want
Get the first one (you can use the rest as well if there are multiple entries matching your search)
This works in every browser since it only uses .map() , Object.keys() and .filter()

Cannot get/fetch keys from an array in 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

javascript / es6 - how to get index of first object value whos array length is greater than 0

I have an object which is full of arrays:
const errors = { name: [], date: ['invalid format'], ... }
I want to find the index (or object key, if I can't get an index) of the first value in the errors object where the array length is greater than one. So in the example above, the date array is the first array in the object that has a length, so I would just return, ideally, 1, or date if necessary.
Anybody know the most concise / fastest way to do this in javascript / es6?
You can use find() on Object.keys() and it will return first result that matches condition or undefined.
const errors = { name: [], date: ['invalid format']}
var result = Object.keys(errors).find(e => errors[e].length);
console.log(result)
JavaScript objects have no inherent order to their properties, so if an index is truly salient you probably want to use an array instead.
At that point it's just something like errors.findIndex(e => e.length > 1), adjusted as you see fit.
You can use for ..in to loop through the object and Object.prototype.toString to check if the value is an array.
Also to find the index you may need to use Object.keys which will create an array of keys from the object. Js Object does not have index
const errors = {
name: [],
test: 1,
date: ['invalid format'],
test2: 2
}
for (var keys in errors) {
if (Object.prototype.toString.call(errors[keys]) === '[object Array]' && errors[keys].length > 0) {
console.log(errors[keys])
}
}

Use pop() with JavaScript Associative Arrays

How can I do something like the following in JS? I would like to imitate .pop() on an object rather than an array.
var deck = {
'cardK' :'13',
'cardQ' :'12',
'cardAJ':'11'
};
var val = deck.pop();
console.log("Key" + val.key );
console.log("Value" + val.val );
It seems like it's not possible.
.pop is only available on an array. In JavaScript, objects (which are essentially associative arrays) are not ordered like an array, so there is no .pop method.
You could use an array:
var deck = [
{ key: 'cardK', val: 13 },
{ key: 'cardQ', val: 12 },
{ key: 'cardAJ', val: 11 },
];
var val = deck.pop();
console.log('key: ' + val.key);
console.log('aa: ' + val.val);
As suggested by other answers, the best solution here might be to use an array of objects. However you could also create your own pop function that removes a key from an object, for example:
function pop(obj) {
var key = Object.keys(obj).pop();
var result = {key: key, val: obj[key]};
delete obj[key];
return result;
}
var val = pop(deck);
You could add a similar pop function to Object.prototype so that you could do deck.pop(), but I would strongly recommend against that type of design.
You are right, it's not possible. See objects as maps or hash tables, rather than "associative arrays". The properties don't have an order and thus a method such as .pop would not make sense (unless of course it would remove a random property, like Python's dictionaries).
If you want to to use .pop and val.key and val.val, you have to create an array of objects instead:
var deck = [
{key: 'cardK', val: '13'},
{key: 'cardQ', val: '12'},
{key: 'cardAJ', val: '11'}
];
As I'm sure you know, .pop is a prototypal Array method, so you can't use it with Javascript objects.
Calling .pop on an array will remove the last element from the array. However, there isn't a "last" key-value pair with objects, as their order is not ever guaranteed. Despite this, if you don't care about order, you could implement a .pop-like function for use with objects, though, again, it wouldn't remove and return the final key-value pair.
Something like this should do the trick:
function pop(obj) {
for (var key in obj) {
var val = obj[key];
delete obj[key];
return {
'key' : key,
'val' : val,
};
};
};
Combined with your code:
var val = pop(deck);
console.log('key: ' + val.key);
console.log('aa: ' + val.val);
When working with this structure, which can be thought of as an associative array, you need to use different techniques. Things like pop(), slice() and even .length will not work as they do with numeric keyed arrays.
I use string keyed object arrays when searching for the key/value pair needs to happen fast.
Here's a jsPef I just created which shows the benefit of your array structure:
http://jsperf.com/bmcgin-object-array-tests (keep in mind the performance goes way up as the array gets bigger)
Also keep in mind the value can be a number, a string, an array, a function, an object ect...

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