I'll start this by saying, I understand there are many ways to do this. This question is an effort to compare different version.
I also understand we're looking for SO to be a QA site, not a QAAAAAAA... site.
So I'll refine the question to make it more focused and end up with one answer.
Given an object:
var obj = {a: 1, b: 2, c: 3};
Find out if the following keys are present:
var keys = ['a', 'b', 'c', 'd']; // 'd' would be flagged although a boolean would suffice
Ideally I'd like to do this in ES5, but ES6 is more than welcome.
Ideally without the use of lodash, but it's more than welcome.
I'm sure there's a lovely combination of the native Array methods that'll work:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
The aim is to have a function or line of code that's small and concise rather than something like:
var obj = {a: 1, b: 2, c: 3};
var keys = ['a', 'b', 'c', 'd'];
var found = keys.length;
for (var i = 0; i < keys.length; i++) {
if (obj.hasOwnProperty(keys[i])) {
found--;
}
}
console.log("Missing:", found);
I'll wade in with the first offering:
var obj = {a: 1, b: 2, c: 3};
var keys = ['a', 'b', 'c', 'd'];
var allPresent = Object.keys(obj).filter(function(item) {
return keys.indexOf(item) !== -1;
}).length === keys.length;
console.log("All present:", allPresent);
Like this:
var obj = {a: 1, b: 2, c: 3};
var keys = ['a', 'b', 'c', 'd'];
alert(keys.every(Object.prototype.hasOwnProperty, obj))
allPresent = keys.reduce(function ( acc, next ) {
return !acc || obj.hasOwnProperty(next);
}, true);
Although Amits answer is probably even smaller and preferred for browsers that support 'every'. (should be all of them by now)
Given object:
var obj = {a: 1, b: 2, c: 3},
keys = ['a','b'];
You can check if it contains key 'a' using this:
Object.keys( obj ).indexOf('a') !== -1
Thanks for comments here is full answer to check what OP requested for full equality:
JSON.stringify( Object.keys( obj ) ) === JSON.stringify( keys )
Or partial equality
JSON.stringify( Object.keys( obj ) ).indexOf( JSON.stringify( keys ) ) !== -1
Related
I want to find what's the position of the following array, according to the table below.
So, here is an example:
I have this array : ['AA','CC','TC']
and I have this table:
Now, according to the array, my first value is 'AA'. So if you notice, we have A and A as the fist index, which we have to read in the table below. So first, we look in the rows of the table, and then we check the columns. we see, that the number of the row and of the columns in the value:12.
So far I have this code in JavaScript:
function cal_extinction_coefficient(str) {
var values_compare= [['Values', 'A','C','T'], ['A', 12,14,16], ['C',23,25,26], ['T',31,34,37]];
var values_to_find=['AA','CC','TC']
let chunk=0;
var all_combLength= values_to_find.length;
for (var i = 0; i < all_combLength; i++) {
for (let j = 0; j < values_compare.length; j++) {
const final= times[j].includes(all_combinations[i].slice(0,1));
}
}
However, I don't know how to access these values... I have the same resolution, but in pandas and with python...
Can someone help me please?
If you are new to JS, try to create your own functions first. It's usually easier than it seems to be.
const data = {
dataFrame: [
['A', 27, 21],
['C', 21, 14]
],
columns: ['Type', 'A','C']
}
const getValue = (xy) => {
[col, row] = xy.split('');
return data.dataFrame.find(x => x[0] == row)?.[data.columns.indexOf(col)];
}
console.log(getValue("AA"));
You could use nested objects:
const type1 = {A: {A: 27, C: 21}, C: {A: 21, C: 14}}
and access your elements with
type1['A']['C']
or
type1.A.C
Using lodash#get you can access the element with
_.get(type1, ['A', 'C'])
Examples:
const type1 = {A: {A: 27, C: 21}, C: {A: 21, C: 14}};
console.log(type1['A']['C']);
console.log(type1.A.C);
console.log(_.get(type1, ['A', 'C']));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>
function select(arr, obj) {
var myKeys = Object.keys(obj);
var myValues = Object.values(obj);
var newObj = {};
for(var i=0; i<myKeys.length; i++) {
if(arr[i] === myKeys[i]) {
newObj[myKeys[i]] = myValues[i];
}
}
return newObj;
}
var arr = ['a', 'c', 'e'];
var obj = {
a: 1,
b: 2,
c: 3,
d: 4
};
var output = select(arr, obj);
console.log(output); // --> { a: 1, c: 3 }
/*
If keys are present in the given array, but are not in
the given object, it should ignore them.
It does not modify the passed in object.
*/
I'm having trouble adding an array as an object property. I created a new Object to store the values in, however it only stores the first instance of arr[i]. I'm confused at this point any help?
Do this instead
for(var i=0; i<arr.length; i++) {
if(myKeys[arr[i]] !== undefined) {
newObj[arr[i]] = myValues[i];
}
}
Your code works only if the index of matching keys is exactly the same.
The problem in your code is that it assumes that the ith value in the array must correspond to the ith key of the object, but that order is not guaranteed.
Here is a functional programming style solution, that uses Obect.fromEntries to construct the returned object:
const select = (arr, obj) =>
Object.fromEntries(arr.filter(key => key in obj).map(key => [key, obj[key]]));
var arr = ['a', 'c', 'e'];
var obj = {a: 1,b: 2,c: 3,d: 4};
var output = select(arr, obj);
console.log(output);
I'd use the relatively recently added Object.fromEntries to create an object directly from a map of a filtered set of keys from your object.
function select (arr, obj) {
// get the keys from obj and filter to those present in arr
var keys = Object.keys(obj).filter(key => arr.includes(key));
// create an array of arrays where each inner array has a key and value
var entries = keys.map(key => [key, obj[key]]);
// call fromEntries with that new array.
return Object.fromEntries(entries);
}
var arr = ['a', 'c', 'e'];
var obj = {
a: 1,
b: 2,
c: 3,
d: 4
};
var output = select(arr, obj);
console.log(output); // --> { a: 1, c: 3 }
/*
If keys are present in the given array, but are not in
the given object, it should ignore them.
It does not modify the passed in object.
*/
All browsers I've tested
Object.keys({ a: 'a', c: 'c', b: 'b' })
on give
["a", "c", "b"]
My question is: Are there Javascript implementations that give something else?
My question is not: Does the standard guarantee it?
Yes there are. This is my implementation that does not return the keys in order:
Object.keys = obj => {
const result = [];
for(let key in obj) result.push(key);
result.sort(() => Math.random() * 2 - 1);
return result;
};
How to I change the object in the array with For-of loop?
Following code:
let arr = ['a', 'b', 'c', 'd', 'e'];
for (let v of arr) {
if (v === 'c') {
v = 'f';
break;
}
}
console.log(arr);
I want to find the first letter c and change it to an f, but arr doesn't get changed, probably because it is not referenced ? But shouldn't the v of arr make that the object v is the same as the one in arr ?
Javascript does not create references to simple values such String. To get array referrenced, you need to let array be an array of objects like [{char : 'a'}, {char : 'b'}, ...]. Then in your iterator you can change elements of array through changing of the char property
let arr = [{char: 'a'}, {char :'b'}, ...];
for (let v of arr) {
if (v.char === 'c') {
v.char = 'f';
break;
}
}
v is not a reference to the array element, it's just a variable that is assigned the value that the array iterator yields. If you assign to it, only the variable v changes but not the array.
To do that, you need to explicitly reference the property with its index and assign to it:
let arr = ['a', 'b', 'c', 'd', 'e'];
for (let [i, v] of arr.entries()) {
if (v === 'c') {
arr[i] = 'f';
break;
}
}
console.log(arr); // ['a', 'b', 'f', 'd', 'e']
An iterator does not provide a way to mutate the underlying structure, you need to do it yourself.
As detailed in the MDN spec, let is declaring a new variable from a copy of your array element. So changing the v will not change the value in the array. This is shared by var and const and is simply just javascripts behaviour. When you create a new object, it starts empty.
Your loop is basically saying "For every element in arr, declare a variable holding a copy of it and then if that variable is c, change that copy to f"
Before you change v both, the array and v point to - or in this case have - the same value:
arr[2] -> 'c' <- v
After you change v it has a different value, but you didn't change the array:
arr[2] -> 'c' v -> 'f'
v and arr[2] are only placeholders, but different ones.
The correct answer:
let arr = ['a', 'b', 'c', 'd', 'e'];
let i = 0;
for (let v of arr) {
if (v == 'c') {
arr[i] = 'f';
break;
}
i++;
}
console.log(arr);
:-P
Basically i want to create a tree structure. For example if you have an array of four items ['a', 'b', 'c', 'd'] then i need a JSON from this which should be
{a: {b: {c: {d: 0} } } }
last item of JSON have value of 0 or it can be anything except object.
The conversion steps are straightforward with simple loop:
Reverse the array, so the last becomes the first to convert (and it becomes the inner-most element of JSON).
Iterate through each element, make key-value pair of the object, wrap it repeatedly.
Done
Sample code:
var array = ['a', 'b', 'c', 'd']; // input array
var json = {}; // output object
array.reverse().forEach(function(el){
if (Object.keys(json).length==0){
json[el] = 0;
}
else{
var outer = {};
outer[el] = json;
json = outer;
}
});
Output
{"a": {"b": {"c": {"d": 0} } } }
In an ES5 environment.
var data = ['a', 'b', 'c', 'd'],
jsObject = data.reduceRight(function (acc, datum) {
var val = {};
val[datum] = acc;
return val;
}, 0),
jsonString = JSON.stringify(jsObject);
document.getElementById('out').textContent = jsonString;
<pre id="out"></pre>