Adding an Array Value as a Javascript Object Property - javascript

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.
*/

Related

In Javascript, given key/value pairs, return values from array of keys

const pairs = { a : 1, b : 2, c : 3 }
const keyArray = [a, b, c]
I'm trying to get a function or w/e that returns [1, 2, 3]. can't think of anything please help
In javascript all keys of an object are actually strings, and can be addressed using the same strings.
Your code is creating an array containing the values of the - possibly uninitialized - variables a, b and c, which then produces [undefined, undefined, undefined], or else whatever those variables contain.
You need to make keyArray contain strings instead, and then you can use the map() function to produce the desired result:
const pairs = { "a" : 1, "b" : 2, "c": 3 }
const keyArray = ["a", "b", "c"]
const values = keyArray.map(key => pairs[key]);
console.log(values);
const pairs = { 'a' : 1, 'b' : 2, 'c': 3 }
const keyArray = ['a', 'b', 'c']
for(const item of keyArray)
{
console.log(pairs[item])
}
You need to make your items inside the array and object as strings
Well since it's Javascript
Object.values() should do it.
const keyArray = Object.values(pairs)
const pairs = { 'a' : 1, 'b' : 2, 'c': 3 }
for(const [key , value] of Object.entries(pairs))
{
console.log(key) // a , b, c
console.log(value) // 1, 2, 3
}

Eliminate duplicates of several arrays

I have 3 arrays:
array1 = [ 'A', 'B', 'A', 'B']
array2 = [ 5, 5, 7, 5]
array3 = [true,true,true,true]
I was wondering if there is any easy way (maybe with lodash) to eliminate the duplicates and end with this:
array1 = [ 'A', 'B', 'A']
array2 = [ 5, 5, 7]
array3 = [true,true,true]
I know I can do a function and compare the previous value, but is there a more clever way to do it?
Update
Please note that I don't need to eliminate the duplicates of each array.
What I looking is a way to eliminate the duplicates "vertically"
Update 2
Please note that each "column" is a record.
record1 = ['A',5,true]
record2 = ['B',5,true]
record3 = ['A',7,true]
record1 = ['B',5,true]
TL;DR
const records = array1.map((a, i) => [a, array2[i], array3[i]]);
const index = {};
records.filter(column => {
const key = JSON.stringify(column);
return key in index ? false : index[key] = true;
});
Huh?
There are a lot of ways to solve this, with varying degrees of efficiency, and the best solution will depend on the size of your data. A simple but naΓ―ve solution iterates over each "column" and checks all of the preceding columns for equality. It looks like this:
const array1 = [ 'A', 'B', 'A', 'B'];
const array2 = [ 5, 5, 7, 5];
const array3 = [true,true,true,true];
const newArray1 = array1.slice(0,1); // column 0 is never duplicate
const newArray2 = array2.slice(0,1);
const newArray3 = array3.slice(0,1);
// loop over columns starting with index 1
outer: for (let i = 1; i < array1.length; i++) {
const a = array1[i];
const b = array2[i];
const c = array3[i];
// check all preceding columns for equality
for (let j = 0; j < i; j++) {
if (a === array1[j] && b === array2[j] && c === array3[j]) {
// duplicate; continue at top of outer loop
continue outer;
}
}
// not a duplicate; add to new arrays
newArray1.push(a);
newArray2.push(b);
newArray3.push(c);
}
console.log(newArray1);
console.log(newArray2);
console.log(newArray3);
.as-console-wrapper{min-height:100%}
As you can see, we have to check each row within each column for equality, every time. If you're curious, the complexity of this is 𝑂(𝑛(𝑛+1)/2) (technically 𝑂(π‘šπ‘›(𝑛+1)/2), where π‘š is 3 for three columns).
For a larger data sets it's advantageous to keep track of values you've already seen in a data structure that's quick to access: A hash, a.k.a. a JavaScript object. Since all of your values are primitive, a quick way to construct a key is JSON.stringify. Some might consider this a "hack"β€”and it's important to note that it will fail with values that can't be represented in JSON, e.g. Infinity or NaNβ€”but it's a fast and easy one with data this simple.
const array1 = ['A', 'B', 'A', 'B'];
const array2 = [5, 5, 7, 5];
const array3 = [true, true, true, true];
const newArray1 = [];
const newArray2 = [];
const newArray3 = [];
const index = {};
for (let i = 0; i < array1.length; i++) {
const a = array1[i];
const b = array2[i];
const c = array3[i];
const key = JSON.stringify([a,b,c]);
if (key in index) {
// duplicate; skip to top of loop
continue;
}
// not a duplicate; record in index and add to new arrays
index[key] = true;
newArray1.push(a);
newArray2.push(b);
newArray3.push(c);
}
console.log(newArray1);
console.log(newArray2);
console.log(newArray3);
.as-console-wrapper{min-height:100%}
The complexity of this is 𝑂(𝑛), or maybe 𝑂(2π‘šπ‘›) where π‘š, again,
is 3 for three columns, and the 2 is another π‘š to very roughly account for the cost of JSON.stringify. (Figuring out the cost of hash access is left as an exercise for the pedants among us; I'm content to call it 𝑂(1).)
That's still pretty verbose. Part of the reason is that using three different variables for the dataβ€”which is really a single "table"β€”leads to a lot of repetition. We can preprocess the data to make it easier to deal with. Once it's "transposed" into a single two-dimensional array, we can use Array.prototype.filter with the key technique from above, for some very terse code:
const array1 = ['A', 'B', 'A', 'B'];
const array2 = [5, 5, 7, 5];
const array3 = [true, true, true, true];
// turn "columns" into "rows" of a 2D array
const records = array1.map((a, i) => [a, array2[i], array3[i]]);
const index = {};
const newData = records.filter(column => {
const key = JSON.stringify(column);
return key in index ? false : index[key] = true;
});
console.log(newData);
.as-console-wrapper{min-height:100%}
Of course, pre-processing isn't free, so this code isn't any more performant than the more verbose version; you'll have to decide how important that is to you. If you want you can now extract the columns from newData into three variables (newData.forEach(([a,b,c]) => { newArray1.push(a); newArray2.push(b); /* ... */ })), but for many purposes the "transposed" 2D array will be easier to work with.
You can use ES6 Set https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
Set -> lets you store unique values of any type, whether primitive values or object references.
and then convert back to an array
check this snippet
const array1 = ['A','B','A','B']
const array2 = [5,5,7,5]
const array3 = [true,true,true,true]
const uniqA1= new Set(array1)
const uniqA2= new Set(array2)
const uniqA3= new Set(array3)
console.log(Array.from(uniqA1))
console.log(Array.from(uniqA2))
console.log(Array.from(uniqA3))
Hope it helps
You need to find duplicate elements with same indexes in all arrays and then filter out those elements.
var array1 = ['A', 'B', 'A', 'B'],
array2 = [5, 5, 7, 5],
array3 = [true, true, true, true];
var dupes = []
var arrays = [array1, array2, array3];
arrays.forEach(function(arr, i) {
arr.forEach((e, j) => !this[e] ? this[e] = true : dupes[i] = (dupes[i] || []).concat(j))
}, {})
var index = dupes[0].filter(e => dupes.every(a => a.includes(e)))
var result = arrays.map(e => e.filter((a, i) => !index.includes(i)))
console.log(result)
You're going to need a couple of helper functions (lodash provides them also):
let zip = (...arys) => arys[0].map((_, i) => arys.map(a => a[i]));
let uniq = (ary, key) => uniq2(ary, ary.map(key), new Set);
let uniq2 = (ary, keys, set) => ary.filter((_, i) => !set.has(keys[i]) && set.add(keys[i]))
// test
var array1 = ['A', 'B', 'A', 'B'];
var array2 = [5, 5, 7, 5];
var array3 = [true, true, true, true];
var [x, y, z] = zip(
...uniq(
zip(array1, array2, array3),
JSON.stringify
)
);
console.log(x, y, z)
Another way, with filter():
array1 = ['A', 'B', 'A', 'B'];
array2 = [5, 5, 7, 5];
array3 = [true, true, true, true];
uniqueArray1 = array1.filter(function(item, pos) {
return array1.indexOf(item) == pos;
})
uniqueArray2 = array2.filter(function(item, pos) {
return array2.indexOf(item) == pos;
})
uniqueArray3 = array3.filter(function(item, pos) {
return array3.indexOf(item) == pos;
})
console.log(uniqueArray1);
console.log(uniqueArray2);
console.log(uniqueArray3);
One method I can think of is using an object to keep track, which will also coincidentally remove any duplicates as keys have to be unique. The only thing is I can think of how to extract it back into an array for now. I will think about it tomorrow.
This utilizes jquery for deep cloning. If you want it only in vanilla javascript, you could probably just implement a deep clone function.
var array1 = [ 'A', 'B', 'A', 'B'];
var array2 = [ 5, 5, 7, 5];
var array3 = [true,true,true,true];
all_arrays = [array1, array2, array3];
let obj = {};
for (let i = 0; i < all_arrays[0].length; i++)
{
let new_obj = recursive_objects(all_arrays, 0, i)
$.extend(true, obj, new_obj);
}
console.log(obj);
function return_array(array, temp_obj)
{
let keys = Object.keys(temp_obj);
for (let key of keys)
{
}
}
function recursive_objects(arrays, arrays_index, index)
{
let obj = {}
if (arrays_index < arrays.length)
{
obj[arrays[arrays_index][index]] = recursive_objects(arrays, ++arrays_index, index);
}
return obj;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How to place each value of an object into an array

I have two objects:
a = {A: 1, B: 2};
a = {C: 3, D: 4};
I need to put the property values of the objects in to one array. So, i'm doing this by iterate each of the objects, but what next, pushing it into one array returns two separated...
$.each(a, function(_key, _val) {
var arr = [];
arr.push(_val);
console.log(arr);
});
How to do this? Is it possible?
I need this: arr = [1, 2, 3, 4];
You are initializing the arr inside the each everytime. Try this:
var arr = [];
$.each(a, function(_key, _val) {
arr.push(_val);
console.log(arr);
});
Here is a fiddle:
https://jsfiddle.net/aarLgmtL/
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
function join(source, target) {
$.each(source, function(_key, _val) {
target.push(_val);
});
}
var arr = [];
join(a, arr);
join(b, arr);
$("#result").html(JSON.stringify(arr));
You could try using .concat as well. Here is an example from w3schools:
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var children = hege.concat(stale);
http://www.w3schools.com/jsref/jsref_concat_array.asp
Is this what you are looking for?
Don't initialize array in $.each function. It will assign new array every time $.each function call so it end up with last array element in arr variable.
a = {
A: 1,
B: 2
};
b = {
C: 3,
D: 4
};
var arr = [];
function pushToArray(a) {
$.each(a, function(_key, _val) {
arr.push(_val);
});
}
pushToArray(a);
pushToArray(b);
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Make sure that you don't define different object with same name else end up with last object assigned to that variable.
You can simply achieve this by using Object.assign
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
var copy = Object.assign(a, b);
var result =[];
for(var i in copy){
result.push(copy[i]);
}
console.log(result);
Thanks.
The approach outlined below first creates two separate arrays, one from a and one from b, and then concatenates them together (with a little help from the jQuery Array#map method.)
a = {A: 1, B: 2};
b = {C: 3, D: 4};
var arrayFromA = $.map(a, function(value, index) {
return [value];
});
var arrayFromB = $.map(b, function(value, index) {
return [value];
});
finalArray = arrayFromB.concat(arrayFromA);

Getting key with the highest value from object

I have a object like that one:
Object {a: 1, b: 2, undefined: 1}
How can I quickly pull the largest value identifier (here: b) from it? I tried converting it to array and then sorting, but it didn't work out, since it got sorted alphabetically (and it seems like a overkill to juggle data back and forth just for getting one value out of three).
For example:
var obj = {a: 1, b: 2, undefined: 1};
Object.keys(obj).reduce(function(a, b){ return obj[a] > obj[b] ? a : b });
In ES6:
var obj = {a: 1, b: 2, undefined: 1};
Object.keys(obj).reduce((a, b) => obj[a] > obj[b] ? a : b);
Using Underscore or Lo-Dash:
var maxKey = _.max(Object.keys(obj), function (o) { return obj[o]; });
With ES6 Arrow Functions:
var maxKey = _.max(Object.keys(obj), o => obj[o]);
jsFiddle demo
Here is a suggestion in case you have many equal values and not only one maximum:
const getMax = object => {
return Object.keys(object).filter(x => {
return object[x] == Math.max.apply(null,
Object.values(object));
});
};
This returns an array, with the keys for all of them with the maximum value, in case there are some that have equal values.
For example: if
const obj = {apples: 1, bananas: 1, pears: 1 }
//This will return ['apples', 'bananas', 'pears']
If on the other hand there is a maximum:
const obj = {apples: 1, bananas: 2, pears: 1 }; //This will return ['bananas']
---> To get the string out of the array: ['bananas'][0] //returns 'bananas'`
Supposing you've an Object like this:
var obj = {a: 1, b: 2, undefined: 1}
You can do this
var max = Math.max.apply(null,Object.keys(obj).map(function(x){ return obj[x] }));
console.log(Object.keys(obj).filter(function(x){ return obj[x] == max; })[0]);
{a: 1, b: 2, undefined: 1}
The best work around I've seen is this
const chars = {a: 1, b: 2, undefined: 1}
//set maximum value to 0 and maxKey to an empty string
let max = 0;
let maxKey = "";
for(let char in chars){
if(chars[char]> max){
max = chars[char];
maxKey= char
}
}
console.log(maxKey)
Very basic method. might be slow to process
var v = {a: 1, b: 2, undefined: 1};
function geth(o){
var vals = [];
for(var i in o){
vals.push(o[i]);
}
var max = Math.max.apply(null, vals);
for(var i in o){
if(o[i] == max){
return i;
}
}
}
console.log(geth(v));
Combination of some ideas from other answers. This will get all the keys with the highest value, but using the spread operator to get the maximum value and then filter array method:
const getMax = object => {
let max = Math.max(...Object.values(object))
return Object.keys(object).filter(key => object[key]==max)
}
let obj = {a: 12, b: 11, c: 12};
getMax(obj)
let data = {a:1,b:2,undefined:3}
let maxValue = Object.entries(data).sort((x,y)=>y[1]-x[1])[0]
note: this is a very expensive process and would block the event loop if used with objects of large sizes(>=1000000). with large array slice the entries and call the above method recurrently using setTimeout.
If you need to return an array from an object with the keys for all duplicate properties with the (same or equal) highest value, try this:
const getMax = Object.keys(object)
.filter(x => {
return object[x] == Math.max.apply(null,
Object.values(object));
})
var object = { orange: 3, blue: 3, green: 1}
console.log(getMax) // ['orange', 'blue']

in javascript, is there an easy way to sort key-value pairs by the value, and return the key?

In javascript, is there an easy way to sort key-value pairs by the value (assume the value is numeric), and return the key? A jQuery way to do this would be useful as well.
(There are a lot of related questions about key-value pairs here, but I can't find one specifically about sorting.)
There's nothing easy to do this cross-browser. Assuming an array such as
var a = [
{key: "foo", value: 10},
{key: "bar", value: 1},
{key: "baz", value: 5}
];
... you can get an array of the key properties sorted by value as follows:
var sorted = a.slice(0).sort(function(a, b) {
return a.value - b.value;
});
var keys = [];
for (var i = 0, len = sorted.length; i < len; ++i) {
keys[i] = sorted[i].key;
}
// keys is ["bar", "baz", "foo"];
Let's assume we have an Array of Objects, like:
var data = [
{foo: 6},
{foo: 2},
{foo: 13},
{foo: 8}
];
We can call Array.prototype.sort()help, use Array.prototype.map()help to map a new array and Object.keys()help to grab the key:
var keys = data.sort(function(a,b) {
return a.foo - b.foo;
}).map(function(elem, index, arr) {
return Object.keys(elem)[0];
});
Be aware of, Array.prototype.map() requires Javascript 1.6 and Object.keys() is ECMAscript5 (requires Javascript 1.8.5).
You'll find alternative code for all those methods on MDC.
As far as I know, there isn't a built-in Javascript function to sort an array by its keys.
However, it shouldn't take too much code to do it: just extract the keys into their own array, sort them using the normal sort function, and rebuild the array in the right order. Something like this should do the trick:
function SortArrayByKeys(inputarray) {
var arraykeys=[];
for(var k in inputarray) {arraykeys.push(k);}
arraykeys.sort();
var outputarray=[];
for(var i=0; i<arraykeys.length; i++) {
outputarray[arraykeys[i]]=inputarray[arraykeys[i]];
}
return outputarray;
}
Now you can just call your function like so:
var myarray = {'eee':12, 'blah':34 'what'=>66, 'spoon':11, 'snarglies':22};
myarray = SortArrayByKeys(myarray);
And the output will be:
{'blah':34, 'eee':12, 'spoon':11, 'snarglies':22, 'what':66}
Hope that helps.
Working test page here: http://jsfiddle.net/6Ev3S/
Given
var object = {
'a': 5,
'b': 11,
'c': 1,
'd': 2,
'e': 6
}
You can sort object's keys by their values using the following:
Object.keys(object).sort(function (a, b) {
return object[a] - object[b]
}))
Result
[ 'c', 'd', 'a', 'e', 'b' ]
If you can't count on the exended array and object properties,
you can use the original Array methods-
function keysbyValue(O){
var A= [];
for(var p in O){
if(O.hasOwnProperty(p)) A.push([p, O[p]]);
}
A.sort(function(a, b){
var a1= a[1], b1= b[1];
return a1-b1;
});
for(var i= 0, L= A.length; i<L; i++){
A[i]= A[i][0];
}
return A;
}
//test
var Obj={a: 20, b: 2, c: 100, d: 10, e: -10};
keysbyValue(Obj)
/* returned value: (Array)
e,b,d,a,c
*/

Categories