JavaScript Updating a dictionary from array of values using array of keys - javascript

I have a dictionary (nested), an array of keys, and an array of values. I need to update the dictionary with the given values using the array of keys as the address. Example:
dict = {"a":{"b":[{"c":1,"d":2},{"c":3,"d":4}]}}
address = [["a","b",0,"c"],["a","b",1,"d"]]
value = [10,40]
The desired output is:
dict = {"a":{"b":[{"c":10,"d":2},{"c":3,"d":40}]}}
How can I do this in JavaScript?

You could take a function for setting the value and reduce the path to the inner property.
function setValue(object, [...keys], value) {
var last = keys.pop();
keys.reduce((o, k) => o[k], object)[last] = value;
}
var dict = { a: { b: [{ c: 1, d: 2 }, { c: 3, d: 4 }] } },
address = [["a", "b", 0, "c"], ["a", "b", 1, "d"]],
value = [10, 40],
i,
l = address.length;
for (i = 0; i < l; i++) setValue(dict, address[i], value[i]);
console.log(dict);

You could do something along these lines:
const dict = {"a":{"b":[{"c":1,"d":2},{"c":3,"d":4}]}},
address = [["a","b",0,"c"],["a","b",1,"d"]],
value = [10,40];
// For each address
address.forEach((path, index) => {
let el = dict;
// For each address fragment
for (let i = 0; i < path.length; i++) {
// If it's not the last fragment
if (i < path.length - 1) {
// Navigate to the next
el = el[ path[i] ];
} else {
// Otherwise, set the value
el[ path[i] ] = value[index];
}
}
});
console.log(JSON.stringify(dict));

Related

find value (and key) of an object in array (JS)

I am writing a function that will iterate through an of objects to find if key:value pair exists and if so, it adds into another array (in case there are multiple matches)
The array contains objects. The function takes as argument what key and value you're looking for and then iterates through array till it finds it. As you can see, key is a variable then and my problem is I am not sure how to access object property when referring to as a variable value.
for (let i = 0; i < arr.length; i++) {
if (arr[i].[key] == value) {
result.push(arr[i]);
}
}
I thought maybe putting it in [key] would help, but I was obviously wrong. I tried googling how to do it, but I guess i can't put it in words right .
You are confusing dot notation with bracket notation.
Remove the .; arr[i].[key] == value1 should be arr[i][key] == value.
const arr = [{
'a': 'b'
}]
key = 'a'
value = 'b'
const result = []
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] == value) {
result.push(arr[i]);
}
}
console.log(result)
You can simplify the code by using filter:
const arr = [{
'a': 'b'
}]
key = 'a'
value = 'b'
const result = arr.filter(e => e[key] == value)
console.log(result)
You can use ES6+ and ternary true ( && == only true action )
const arr = [{
a: 'b'
}];
const key = 'a';
const value = 'b';
const result = [];
for (const item of arr) {
(item[key] === value) && result.push(item)
};
console.log(result);
You can simplify the code by using filter:
const arr = [{
a: 'b'
}];
const key = 'a';
const value = 'b';
const result = [];
for( const item of arr ) {
( item[key] === value ) && result.push( item )
};
console.log( result );
use Array.prototype.filter()
You should know upfront what exact property name you're willing to reference to:
const arr = [
{name:"Evan", age:28},
{name:"John", age:23},
{name:"Anne", age:28},
];
const searchProp = "age";
const searchValue = 28;
const result = arr.filter((user) => user[searchProp] === searchValue);
console.log(result)
You are almost there, just get rid of the extra . between [i] and [key]:
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] == value) {
result.push(arr[i]);
}
}
However, there would be a simpler and more straight-forward way, using filter:
const result = arr.filter(obj => obj[key] == value)
Example:
const arr = [
{ a: 1, b: 1 },
{ a: 1, b: 2 },
{ a: 2, b: 1 },
{ a: 2, b: 2 }
]
const key = 'b'
const value = 1
const result = arr.filter(obj => obj[key] == value)
console.log(result)
// Output: [{ a: 1, b: 1 }, { a: 2, b: 1 }]

Javascript: key/value storage in object with multilevel nesting

I have been given two arrays:-
var keys = ['a.b', 'a.c.d', 'a.e', 'h[0]'];
var values = [10, 20, {}, 40];
The output that I want is:-
{
a: {
b: 10,
c: {
d: 20
},
e: {}
},
h: [40]
}
What I have tried so far is
let constructObject = (keys, values) => {
let output = {};
for(let i = 0; i<keys.length; i++) {
let props = keys[i].split('.');
for(let j=0; j<props.length;j++) {
if(props.length > (j+ 1)) {
if(output[props[j]] == undefined) {
output[props[j]] = {};
}
} else {
output[props[j]] = values[i];
}
}
}
return output;
}
The above code is not nesting deeper. I tried to store nested level key also using for loop but could not get any way to store keys, As javascript only gives way to store value not nested level keys.
You could separate the pathes into smaller parts, like properties and indices and build new object by respecting the next key and decide if an array or an object has to be taken.
function setValue(target, keys, value) {
const
isWrapped = s => s.startsWith('[') && s.endsWith(']'),
unwrap = s => isWrapped(s) ? s.slice(1, -1) : s,
path = keys.match(/\[[^\]+]\]|[^\.\[\]]+/g),
last = path.pop();
path
.reduce((o, k, i, { [i + 1]: next = last }) =>
o[unwrap(k)] = o[unwrap(k)] || (isWrapped(next) ? [] : {}), target)
[unwrap(last)] = value;
}
var keys = ['a.b', 'a.c.d', 'a.e', 'h[0]'],
values = [10, 20, {}, 40],
i,
l = keys.length,
result = {};
for (i = 0; i < l; i++) setValue(result, keys[i], values[i]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript - Adding multiple values to keys

I am trying to find the places of each letter in a sentence by using "dictionaries". The problem is I want to find all the places that each letter is and not only the last one. I am very new to JavaScript and couldn't figure out the way to do it.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ )
if (!stringArgument[i] in dict){
dict[stringArgument[i]] = [];
}else{
dict[stringArgument[i]] = [i+1]
}
return dict
}
var a = letters('Lost time is never found again.');
console.log(a);
naturally gives this output:
{ L: [ 1 ], o: [ 17 ], s: [ 10 ], t: [ 5 ]...
but it should give this:
{ L: [ 1 ], o: [ 2, 17 ], s: [ 3, 10 ], t: [ 4, 5 ]...
Also each letter is saved to the dictionary at the same order they appear in the sentence, how can I order the letters alphabetically?
What you need is a function that gets the positions of a character in a given string.
Try this:
function findAllPositions(char, content) {
var result = [];
let index = content.indexOf(char);
while(index !== -1) {
result.push(index);
index = content.indexOf(char, index + 1);
}
return result;
}
findAllPositions('o', 'Lost time is never found again.'); // Result =  [1, 20]
Using this we can update the letter function as follows:
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (const char of stringArgument) {
dict[char] = findAllPositions(char, stringArgument)
}
return dict;
}
letters('is again.')
/*
{
"i": [0, 5],
"s": [1],
"a": [2, 4],
"g": [3],
"n": [6],
".": [7]
}
*/
You need to have
parantheses for the check
if (!(stringArgument[i] in dict)) {
create an array if the above is true
push the postion to the array
For getting a sorted output, you could take the entries of the object, apply a sorting by taking the key and show the result in order.
Object have an insertation oder for not positive 32 bit numbers (like indixes) or symbols. The index like numbers are sorted by value and appears first in the object.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
if (!(stringArgument[i] in dict)) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters('Lost time is never found again.');
Object
.entries(a)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([key, positions]) => console.log(key, ...positions));
console.log(a);
First, for any item, if it is not in an empty array:
var notInDict = !(stringArgument[i] in dict);
If not in dict, then initialize an empty array and push the item in it using
dict[stringArgument[i]].push(i + 1);
Try this.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, "");
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
var notInDict = !(stringArgument[i] in dict);
if (notInDict) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters("Lost time is never found again.");
console.log(a);
you are assigning a new array at each iteration
dict[stringArgument[i]] = [i+1]
what you need to do is push the new position to existing array.
dict[stringArgument[i]].push(i+1)
also, remove the else block
function letters(stringArgument) {
stringArgument = stringArgument.toLowerCase().replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ ){
if (!dict.hasOwnProperty(stringArgument[i])){
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i+1);
}
//sorting
var letters = Object.keys(dict); //returns a array
letters.sort();
var sortedDic = {};
for(var i in letters) {
sortedDic[letters[i]] = dict[letters[i]];
}
return sortedDic;
}
var a = letters('Lost time is never found again.');
console.log(a);
for the first part you can also do that:
let sentence = 'Lost time is never found again.'
let tabLetters = [...sentence.replace(/ /g,'')].reduce((a,c,i)=>
{
if (!a[c]) a[c] = [i+1]
else a[c].push(i+1)
return a
},{})
document.write(JSON.stringify(tabLetters))

How to find unique key with desire array value?

I want to get unique p which c values contain all desire_c value !
So here object's p:1 has c value like 1,2,3 . That is match desire_c array value , so I want to get
{p:1} as final result !
Here I am looping in using for loop :(
var object = [{p:1,c:1},{p:1,c:2},{p:1,c:3},{p:2,c:1},{p:3,c:3}];
var desire_c = [1,2,3];
var helper = {};
for(var o in object) {
var current = object[o];
if(typeof helper[current.p] != 'object') {
helper[current.p] = {};
}
helper[current.p][current.c] = null;
}
for(var c of helper) {
for(var d in desire_c) {
c[desire_c[d]]
}
}
You could take a map for p and a set for each c value and check then if all wanted values are in a set.
var object = [{ p: 1, c: 1 }, { p: 1, c: 2 }, { p: 1, c: 3 }, { p: 2, c: 1 }, { p: 3, c: 3 }],
desire_c = [1, 2, 3],
map = new Map,
result;
object.forEach(({ p, c }) => map.has(p) ? map.get(p).add(c) : map.set(p, new Set([c])));
result = [...map.keys()].filter(p => desire_c.every(c => map.get(p).has(c)));
console.log(result);
You can use this auxiliary function to find the unique value:
function findKey(objects, desire){
const map = {}; // Creates a new object to map all keys to all their values, instead of having an array of objects
objects.forEach(obj => {
map[obj.p] = map[obj.p] || []; // Ensures the key has an array of values before pushing a new value
map[obj.p].push(obj.c);
});
return Object.keys(map).find(key => desire.every(des => map[key].includes(des))); // Tries to find a key that contains all desired values
}
Then, just call it like that:
findKey(object, desire_c); // Returns 1 for your example
Please check below code.
var desire_c = [1,2,3];
var data=[{p:1,c:1},{p:1,c:2},{p:1,c:3},{p:2,c:1},{p:3,c:3}];;
var helper = {},element = "p";
for (var i = 0; i < data.length; i++) {
if (!helper[data[i][element]])
helper[data[i][element]] = [];
helper[data[i][element]].push(data[i]["c"]);
};
for (key in helper) {
if (helper.hasOwnProperty(key)) {
if (helper[key].length){
var arr=helper[key];
if(JSON.stringify(arr)==JSON.stringify(desire_c))
{
console.log({"p":key});
}
}
}
}
const hash = {};
for(const {p, c} of object){
if(!hash[p]){
hash[p] = desire_c;
}
hash[p] = hash[p].filter(n => n !== c);
}
const result = [];
for(const [key, val] of Object.entries(hash))
if(!val.length) result.push(key);
This just goes over every p and c in the array, and removes c from the array stored inside the hashtable under p. This array is initialized to your wanted array, so if all elements are removed from it (!val.length) the corresponding key is the one we are looking for.

Array of objects with key/value pairs from given arrays of keys & values

I am trying to return an array of key-value pairs: [{"a": 1},{"b": 2},{"c": 3}] from a given array of keys: ["a", "b", "c"] and an array of values: [1, 2, 3]
I have tried this:
let arr = [], obj = {}, key, val;
const keyValuePairs = (k, v) => {
if (k.length === v.length) {
for (var i = 0; i < k.length; i++) {
key = k[i]; val = v[i];
arr[i] = {key: val};
}
} return arr;
};
keyValuePairs(["a", "b", "c"], [1, 2, 3]);
But it's returning - [ { key: 1 }, { key: 2 }, { key: 3 } ]
How can I do it?
If you're targeting a new enough browser, or are using babel, there is a new syntax that allows this easily:
arr[i] = {[key]: val};
Otherwise you will need to use multiple lines to set the key
let arr = [], obj = {}, key, val;
const keyValuePairs = (k, v) => {
if (k.length === v.length) {
for (var i = 0; i < k.length; i++) {
key = k[i]; val = v[i];
var newObj = {};
newObj[key] = val;
arr[i] = newObj;
}
} return arr;
};
Just general code comments: You have a bunch of variables out of the scope of the function. It's also quite verbose. You can write the entire function like this:
const keyValuePairs = (k, v) => (
k.map((key, index) => ({ [key]: v[index] }))
);
a = ["a", "b", "c"], b = [1, 2, 3]
c = a.map((k, i) => ({[k]: b[i]}))
console.log(JSON.stringify(c))
How do I zip two arrays in JavaScript?
Try this(simple solution):
var answer = keyValuePairs(["a", "b", "c"], [1, 2, 3]);
console.log(answer);
function keyValuePairs(arrOne, arrTwo){
var returnArr = [];
for(var i = 0; i < arrOne.length; i++){
var obj = {};
obj[arrOne[i]] = arrTwo[i];
returnArr[i] = obj;
}
return returnArr;
}
using lodash you can do this in one line with _.map or the vanilla Array.prototype.map and using the index i to stripe across the arrays.
var keys = 'abc'.split('');
var values = '123'.split('');
var result = _.map(keys, (key, i) => ( { [keys[i]] : values[i] } ) );
console.log(JSON.stringify(result));
yields:
[{"a":"1"},{"b":"2"},{"c":"3"}]
you can also continue this pattern dimensionally:
var keys = 'abc'.split('');
var values = '123'.split('');
var valuesValues = 'xyz'.split('');
var result = _.map(keys, (key, i) => ( { [keys[i]] : { [ values[i] ]: valuesValues[i] } } ) );
console.log(JSON.stringify(result));
yields:
[{"a":{"1":"x"}},{"b":{"2":"y"}},{"c":{"3":"z"}}]
you can use reduce method also as per your requirement.
see below example..
let keys = ["a", "b", "c"],
values = [1, 2, 3],
result = keys.reduce((r,v,i)=>r.concat({[v]:values[i]}),[]);
console.log(result);;

Categories