I have the following data arrays (a, b and c).
let a = [a1, a2, a3];
let b = [b1, b2, b3];
let c = [c1, c2, c3];
But I need the data as in array d. Is it possible to get the array d by combining a, b and c in javascript? Is there any simple method that achieves it or I've to iterate each array and conditionlly add them?
let d = [
{x: a1, y: b1, z: c1},
{x: a2, y: b2, z: c2},
{x: a3, y: b3, z: c3}
]
If I understand the question correctly, In your case you are accessing elements of multiple arrays at a specific index position in each iteration. I can't think of any shortcut to handle this. You might need to go the iterative way. Below code could help.
a = ["a1","a2","a3"]
b= ["b1", "b2", "b3"]
c= ["c1", "c2", "c3"]
// Input array
f = [a, b, c];
const length = f.length;
d = Array.from({length}).map((_val, index1) => {
return Array.from({length}).reduce((acc, _val, index2) => {
acc[f[index2][index1]] = f[index2][index1];
return acc;
}, {})
});
console.log(d);
Related
Lets suppose I have object like this:
var obj = {a : 5, b : 10, c : 15, d : 20, e : 20, f : 25};
I would like to get top 3 highest values - notice that d and e key have the same value and I need to get the keys also, so it would looks like:
Highest values:
f - 25
d - 20
e - 20
also if there are for example six values and four are identical:
var obj2 = {a:1, b:1, c:1, d:1, e:0,8, f: 0,5};
I need to show 4 highest.
Highest values:
a-1
b-1
c-1
d-1
I guess there is need to iterate over ALL object properties to get Math.max, but I also need a something to count 3 max numbers WITH their keys, and if there is more max (all the same) I need to "get them all!".
EDIT: there are great answers atm, so I guess I will not finish this code and just use given examples :)
This is an example implementation, with annotations to explain what is happening at each step.
function maxValues(o, n) {
// Get object values and sort descending
const values = Object.values(o).sort((a, b) => b - a);
// Check if more values exist than number required
if (values.length <= n) return o;
// Find nth maximum value
const maxN = values[n - 1];
// Filter object to return only key/value pairs where value >= maxN
return Object.entries(o)
.reduce((o, [k, v]) => v >= maxN ? { ...o, [k]: v } : o, {});
}
const a = maxValues({
a: 5,
b: 10,
c: 15,
d: 20,
e: 20,
f: 25
}, 3);
console.log(a);
const b = maxValues({
a: 1,
b: 1,
c: 1,
d: 1,
e: 0.8,
f: 0.5
}, 3);
console.log(b);
const c = maxValues({
a: 5,
b: 10,
}, 3);
console.log(c);
The callback passed to the Array.prototype.reduce function can be expanded out to the following:
return Object.entries(o)
.reduce(function (obj, [key, value]) {
if (v >= maxN) {
return Object.assign(obj, {
[key]: value
});
} else {
return obj;
}
}, {});
Instead, I condensed it down using an Arrow Function Expression, ternary operator, and spread syntax.
The ternary operator is essentially shorthand for an if/else statement. E.g.
condition ? true : false;
// or
v >= maxN ? { ...o, [k]: v } : o;
The spread syntax allows an iterable value to be expanded in place. In this instance, it's being used to copy existing key/value pairs from one object literal to another.
const a = { first_name: 'Rob', gender: 'male' };
const b = { ...a, username: 'fubar' };
console.log(b); // { first_name: 'Rob', gender: 'male', username: 'fubar' };
Simply,
Sort the object based on its values using, Object.entries
Get the least value you can filter.
Filter the entries and return as Object using Object.fromEntries.
function getTopValues(obj, topN)
{
var sortedEntries = Object.entries(obj).sort(function(a,b){return b[1]-a[1]});
var last = sortedEntries[topN-1][1];
var result = sortedEntries.filter(function(entry){
return entry[1] >= last;
});
console.log(Object.fromEntries(result));
}
getTopValues({a:5, b:10, c:15, d:20, e:20, f:25}, 3);
getTopValues({a:1, b:1, c:1, d:1, e:0.8, f: 0.5}, 3);
getTopValues({a:1, b:1, c:1, d:1, e:0.8, f: 0.5}, 5);
So, you want to find the top 3 highest and if there are multiple identical highest then you want to include all of that.
This problem is asked in a slightly weird fashion.
I am going to assume that if there is something like a:1 b:1 c:2 d:2 e:3,
you would like to include a,b,c and d.
First of all, you only have to keep track of the keys because you can get the values instantly at the end.
Ok! Let's start. (efficient but ugly)
class Numandamount {
constructor(number, amount) {
this.number = number;
this.amount = amount;
}
}
//That's just a class to link numbers and their amounts
var numtoamount = [];
//Now let's fill that array!
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
var num = obj.property;
var found = false;
for(Numandamount naa in numtoamount){
if(naa.number == num){
naa.amount++;
found = true;
}
}
if(!found){
naa.push(new Numandamount(num,1));
}
}
}
//The array is done!
numtoamount.sort(function(a,b){return b.number-a.number});
//Now all we have to do is loop through it!
var count = 0; // keep track of how many we did
var i = 0;
while(count<4 && i<numtoarray.length){
count += numtoamount[i].amount;
i++;
}
//BOOOM WE DID IT
// I is the biggest index so all we have to do is:
for(var j = 0;j<i;j++){
console.log("We have "+numtoamount[j].amount+" "+numtoamount[j].number+"'s");
}
For eg. it will print out for this example obj: {a:1 b:1 c:4 d:6 e:7 f:4}
We have 1 7's
We have 1 6's
We have 2 4's
If you would like some other implementation please comment below!
I put my heart into this <3
I would start with transforming your object into an array of objects:
const arr = []
for (var key in obj){
arr.push( {[key]: obj[key]} )
}
Now you have an array that looks like this:
[
{"f": 25},
{"d": 20},
{"e": 20},
{"c": 15},
{"b": 10},
{"a": 5}
]
Now you can sort your objects by the magnitude of their values:
const sortedArray = arr.sort( (a,b) => {
if (Object.values(a)[0] > Object.values(b)[0]) {
return -1
}
})
Which would give:
[
{"f": 25},
{"d": 20},
{"e": 20},
{"c": 15},
{"b": 10},
{"a": 5}
]
Then you can just pick however many values off the top you want. For example
sortedArray.filter( (item, index) => {
if (index <= 2 || Object.values(item)[0] === Object.values(sortedArray[0])[0]) {
return item
}
})
Which gives:
[
{"f": 25},
{"d": 20},
{"e": 20}
]
Or in the case of your second object, it would match the n highest values, but also grab any other values that are equal to the highest value.
As a single function:
function sortYourObject(object, number){
var arr = []
for (var key in object){
arr.push( {[key]: object[key]} )
}
const sortedArray = arr.sort( (a,b) => {
if (Object.values(a)[0] > Object.values(b)[0]) {
return -1
}
})
const endresult = sortedArray.filter( (item, index) => {
if (index <= 2 || Object.values(item)[0] === Object.values(sortedArray[0])[0]) {
return item
}
})
return endresult
}
If I have an array that looks like
{X:{A,B,C},Y:{A,B,C}}
Where all the letters are variables
How would I add variable D to the array for the X variable key?
How would I add key Z variable to have the value of an array containing the A variable?
The equivalent of what I'm trying to do in php would just be
$array[x][] = d;
$array[z] = array(a,b);
You can access a multidimensional array like this:
var a = 1, b = 2, c = 3, d = 4;
var ary = [[a,b,c],[a,b,c]];
console.log(ary); //[[1,2,3],[1,2,3]];
ary[0].push(d); //add d to first array;
console.log(ary); //[[1,2,3,4],[1,2,3]];
You can also create an object to act like a lookup table.
var obj = {
x: [a, b, c],
y: [a, b, c]
}
console.log(obj); //{x: [1,2,3], y: [1,2,3]};
obj.x.push(d); //add d to array at x
console.log(obj); //{x: [1,2,3, 4], y: [1,2,3]};
obj.z = [d]; // add new key z with new array [d]
console.log(obj); //{x: [1,2,3, 4], y: [1,2,3], z: [4]};
I have around 30 values stored as variables:
var a = 1,
b = 2,
c = 3,
...
z = 26,
aa = 27,
ab = 28;
that I want to scale. I do so using an array:
array = [a, b, c];
var scale = 5;
for (var i = 0; i < array.length; i++){
array[i] = array[i] * scale; // Some simple arithmetic
}
To get the new scaled value, I need to reassign my variables.
var a = array[0],
b = array[1],
c = array[2],
...
z = array[26],
aa = array[27],
ab = array[28];
This is cumbersome, even if I use destructuring assignment. What is a better way to manage all the information I have?
Using plain variables you won‘t find a smarter way. I‘d suggest to use objects instead as arrays are anonymous because you access the content by index instead of a name:
let groupA = {
a: 1,
b: 2,
c: 3
}
You can then iterate and multiply via
for (let key in groupA) {
if (groupA.hasOwnProperty(key) {
groupA[key] *= 5;
}
}
but you still can access each field individually
console.log(groupA.a);
You have to reassign anyway, but you can do it in a more concise way:
let a = 1,
b = 2,
c = 3;
([a, b, c] = [a, b, c].map(v => v * 5));
console.log(b);
I currently have a situation where I have 2 objects that look like this:
object a = {n: 15, b: 12, v: 10, h: 9} and so on.
object b = {1: e, 2: b, 3: z, 4: w} and so on.
I need to take the values from object b and use them to replace the values in object a. the result would look like:
object c = {n: e, b: b, v: z} etc.
One important thing is that if there are more items in object b than in object a, I still need them added on to the end of object c. so if there are 3 more items in object b, perhaps something like this {24: a, 25: y, 26:w} would happen at the end.
My first thought, of course, is a loop where I would iterate over each item in object a and replace the 'value' with that from object b. But I didn't know if there was a better way, especially with my concern about making sure that all of the items from object b are included in the new object.
Because of that concern, an alternative could be to replace the keys in object b with the keys in object a instead. that way if object a runs out, the last items in object b would't be excluded.
I've also tried:
Object.assign(a, b);
but that only works if the keys are the same, so that won't work. I need whatever happens to match index to index for the two objects.
If it matters, I can change object b to be anything I want as it's static. So, I could do:
object b = [e, b, z] etc. or
object b = {e: e, b: b, z: z}
Whatever makes it easiest to do.
I appreciate any thoughts anyone might have or if you can point me in the direction of a good post covering something like this. I'm currently scouring the internet and trying anything that sounds like it might work but so far, nothing has fit.
It's also worth noting that at this point I'm using pure vanilla JS so if there is a library or something that would make this super easy, I'm open to that.
You could do something like the following
var objectA = {
b: "test",
a: "test2",
c: "test3",
d: "test4"
};
var objectB = ["new", "new2", "new3", "new4", "new5", "new6"];
var index = 0;
for (var prop in objectA) {
if (objectA.hasOwnProperty(prop)) {
objectA[prop] = objectB[index];
index++;
}
}
for(index; index < objectB.length; index++) {
objectA[index] = objectB[index];
}
Couple things though:
The for..in loop is based on order of implementation. So whatever order the properties were added to the object will be the order of the loop.
Functionality like what you are requesting seems like a code smell when viewed out of context. Typically you are not merging two objects like the way you are requesting. If you want to provide further context, a better solution might be offered up.
I am assuming that those letter values in object b are strings, but the example would also work on variables, you just have to remove the quotation marks.
My approach is:
1. Get all the keys in b and a
2. Create an empty object, Loop through the keys in b
3. Using the index of b, i can also get the index of a. This way, when we are iterating the 3rd time, i would be 2 and I can get the keys and values of a and b, which are v:10 and 3: 'z' respectively. Then I map the key of a to the value of b, so the result would be v: 'z'.
4. If b has more keys, just assign current key and value in b to c.
var a = {n: 15, b: 12, v: 10, h: 9};
var b = {1: 'e', 2: 'b', 3: 'z', 4: 'w', 24: 'a', 25: 'y', 26:'w'};
// get all the keys in a
let aKeys = Object.keys(a);
// get all the keys in b
let bKeys = Object.keys(b);
// acc is the accumulated object c,
// at the beginning value of c is {}, it gets bigger as we loop through the keys of b
// i is the ith key in b
let c = bKeys.reduce((acc, _, i) => {
// if a > b then put key value pair of b
if (i > aKeys.length - 1) {
acc[bKeys[i]] = b[bKeys[i]];
} else {
acc[aKeys[i]] = b[bKeys[i]];
}
return acc;
}, {});
console.log(c)
After doing a bit more searching and playing, something I read inspired me to make both objects into arrays instead and then join them into a map. Ended up being super easy. This was the result:
var a = ['a', 'b', 'c'];
var b = [1, 2, 3];
var map = {};
for(var i = 0; i < a.length; i += 1) {
map[ a[i] ] = b[i];
}
console.log(map); // {a: 1, b: 2, c: 3}
Thanks for those who read it!
var objectA = {n: 15, b: 12, v: 10, h: 9};
var objectB = {n: e, b: b, v: z, h: w, a: 1, c: 2};
var objectC = extend({}, objectA, objectB);
function extend(out){
out = out || {};
for (var i = 1, len = arguments.length; i < len; i++){
var obj = arguments[i];
if (!obj) continue;
for (var key in obj){
if (obj.hasOwnProperty(key))
out[key] = (typeof obj[key] === 'object') ? extend(out[key], obj[key])
: obj[key];
}
}
return out;
}
console.log(objectC);
// outputs {n: e, b: b, v: z, h: w, a: 1, c: 2}
It will throw error if e, b, z, w is not defined.
Values of objectA and objectB remain unchanged.
From extend({}, objectA, objectB), it gets the value from objectB to replace objectA, and then objectA to {} without changing the original value of objectA and objectB.
Note: You will need to change the keys in objectB to reflect keys in objectA instead of using 1, 2, 3... as keys.
I have four arrays A,B.C, and D. For example:
// example code is here: length of a is 1 length of b is 4 length of c is 1 length of d is 2.
var a = [1];
var b = [2,3,4,5];
var c = [6];
var d = [7,8];
I want to order those four arrays based on the larger length of the arrays, and I also want the names of the arrays those are in the sorted order. so the output will be:
names of the sorted array are b,d,a,c.
This is how I would do it:
var arr = {}
arr["a"] = [1];
arr["b"] = [2,3,4,5];
arr["c"] = [6];
arr["d"] = [7,8];
Object.keys(arr).sort(function(a, b){ return arr[a].length < arr[b].length; });
I did it way trying to keep the independence of the variables and closer to your original code.
Your comment says you want both the list of input array names and an array resulting from concatenating the input arrays together, in order. You can get both in one step:
var [keys, array] = let (
all = [["a", a], ["b", b], ["c", c], ["d", d]]
.sort(function (a, b) { return a[1].length < b[1].length })
) [
all.map(function (x) { return x[0] }),
all.reduce(function (a, b) { return a.concat(b[1]) }, [])
];
Using your data, keys will contain ["b", "d", "a", "c"] and array will contain [2,3,4,5,7,8,1,6].