Related
This question already has answers here:
Zip arrays in JavaScript?
(5 answers)
Closed 2 months ago.
I have two arrays. One contains a series of dates. The other array contains a series of data. What is the best way to combine the two arrays into one array of objects.
As an example the first element of the first array will be in the same object as the first element in the second array.
HERE ARE THE TWO ARRAYS
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
HERE IS MY EXPECTED OUTPUT
let combinedArray = [{
date: *first element from dates array*,
snowFall: *first element from snowfall array*
},
{
date: *second element from dates array*,
snowFall: *second element from snowfall array*
}]
EXPECTED OUTPUT EX:
let combinedArray = [{date: '2017-01-01', snowFall: 0.98},{date: '2017-01-02', snowFall: 0}]
I do not even know where to begin..
Assuming the arrays are of equal lengths, then this should work:
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const combined = snowfallArray.map((snowfall, index) => ({snowfall, date: datesArray[index]}));
console.log(combined);
assuming your array are the same length:
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const results = [];
for (let i=0; i< snowfallArray.length; i++){
results.push({
date: datesArray[i],
snowFall: snowfallArray[i]
})
}
console.log(results);
I wrote a simple seletionSort as:
function selectionSort(arr) {
let copyArr = [...arr];
let newArr = [];
while (copyArr) {
minimum = Math.min(...copyArr);
newArr.push(minimum);
console.log("newArr", newArr);
copyArr.splice(arr.indexOf(minimum), 1);
console.log("copyArr", copyArr);
}
return newArr;
}
Unfortunately, when apply to arr = [-7, 34, 27, 87, 21, 0, -11],it run endlessly and output:
newArr [ -11 ]
copyArr [ -7, 34, 27, 87, 21, 0 ]
newArr [ -11, -7 ]
copyArr [ 34, 27, 87, 21, 0 ]
newArr [ -11, -7, 0 ]
copyArr [ 34, 27, 87, 21, 0 ]
...
newArr [
-11, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 752 more items
]
What's the problem?
You have two main issues:
Arrays are always truthy, even when they're empty []. Meaning that your while loop will continue to execute as [] will be evaluated as true when used in your while condition. You can change your condition to stop when the length is 0, which can be done by checking if the .length is truthy/falsy.
You're splicing the wrong index from your array. Currently, you're using arr.indexOf(minimum) on your array, but this will give you the index of your element before any elements from copyArray were removed. Meaning that the index of the element from arr doesn't match the index from copyArray. You can change this to find the index using copyArray.indexOf() to find the correct index of the minimum in copyArray
function selectionSort(arr) {
let copyArr = [...arr];
let newArr = [];
while (copyArr.length) {
minimum = Math.min(...copyArr);
newArr.push(minimum);
console.log("newArr", newArr);
copyArr.splice(copyArr.indexOf(minimum), 1);
console.log("copyArr", copyArr);
}
return newArr;
}
console.log(selectionSort([4, 2, 10, 1]));
For a slightly more optimized solution, consider making a function to find the index of your minimum number, and then perform a swap. This way you won't need to iterate the array twice to find the minimum number and then the position of that number
function findMinIndex(arr, start) {
let minIdx = start;
for(let i = start+1; i < arr.length; i++) {
if(arr[i] < arr[minIdx]) {
minIdx = i;
}
}
return minIdx;
}
function selectionSort([...arr]) {
for(let i = 0; i < arr.length-1; i++) {
const minIdx = findMinIndex(arr, i); // get pos of min
// Swap the two elements around
const tmp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = tmp;
}
return arr;
}
console.log(selectionSort([4, 2, 10, 1]));
I want to create an array of object like this :
array_1 :
array(0, 0, 0, 1, 0, 1, 0, 1, 1);
object_2 :
obj: [
{
id: 0,
fonction: 'hey'
},
{
id: 1,
fonction: 'hi'
}
]
So, I want the following output :
result :
obj: [
{
id: 0, // id of object_2
max: 5, // number of id value in array_1
value: 0, // add an empty value
fonction: 'hey' // fonction text in oject_2
},
{
id: 1,
max: 4,
value: 0,
fonction: 'hi'
}
]
Thanks for your help
You can just map your existing object, and count the ids inside your array using the filter + length option
const arr = [0, 0, 0, 1, 0, 1, 0, 1, 1];
const target = [
{
id: 0,
fonction: 'hey'
},
{
id: 1,
fonction: 'hi'
}
];
console.log( target.map( item => ({
...item,
max: arr.filter( v => item.id === v ).length,
value: 0
}) ) );
My goal here is to create an object, 'tallys,' that has a key for each user in a game, and the value assigned to those user keys is an array representing weekly dollar values won in a game. To begin, I assign each user in the game an array of length 26 (representing 26 weeks in the game) with 26 values of '0' to represent $0 values for each week to begin with via this code:
const maxWeek = 25;
let weeks = [];
for (let i=0; i < maxWeek+1; i++) {
weeks.push(0)
};
let tallys = {};
users.forEach(user => {
tallys[user] = weeks;
});
...which results in an object like so:
tallys is {
michaeljpow: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0
],
'Mr. Cheeseburger': [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0
],
'brewster.stanislaw': [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0
],
... etc
}
Then, I run a little for loop to calculate the totals for each user by week ... with the 'j' variable here starting at week 1, and the loop running for as many weeks as the game has been running, like this:
for (let j=1; j<wk+1; j++) {
let sums = await BonusEvents().where({week: j}).sum('dollars_total as d').groupBy('username').select('username');
console.log('sums for week ', j, ' are ', sums);
};
I'm still in good shape at this point -- this gets me what I want, two different 'sums' arrays for the two weeks that have taken place in the game so far:
sums for week 1 are [
{ d: -4.27, username: 'Mr. Cheeseburger' },
{ d: -4.27, username: 'dannuzio' },
{ d: 11.29, username: 'james.johnsonf' },
{ d: -4.27, username: 'brewster.stanislaw' },
{ d: 16.47, username: 'eric.wj.clarke' },
{ d: -4.27, username: 'mikeduin' },
{ d: 11.29, username: 'BH84' },
{ d: -4.27, username: 'kevsims' },
{ d: 11.29, username: 'michaeljpow' },
{ d: 47.58, username: 'superbkn' },
{ d: -4.27, username: 'whpfwashington' },
{ d: -4.27, username: 'benjamininghram' }
]
sums for week 2 are [
{ d: -1.41, username: 'benjamininghram' },
{ d: -1.41, username: 'BH84' },
{ d: -1.41, username: 'brewster.stanislaw' },
{ d: -1.41, username: 'dannuzio' },
{ d: -1.41, username: 'eric.wj.clarke' },
{ d: -1.41, username: 'james.johnsonf' },
{ d: -1.41, username: 'kevsims' },
{ d: -1.41, username: 'michaeljpow' },
{ d: -1.41, username: 'mikeduin' },
{ d: -1.41, username: 'Mr. Cheeseburger' },
{ d: 14.06, username: 'superbkn' },
{ d: -1.41, username: 'whpfwashington' },
]
So here's where things get messy. I modify the previous function to do a forEach on my 'sums' array for each week, with designs on modifying the 'tallys' object to modify the array position assigned to each week with the appropriate dollar value for each user. (Also, lest the 'j-1' here look confusing -- that's because I want the game week of 1 assigned to the 0 position in the array rather than the first position):
for (let j=1; j<wk+1; j++) {
let sums = await BonusEvents().where({week: j}).sum('dollars_total as d').groupBy('username').select('username');
sums.forEach(weekSum => {
tallys[weekSum.username][j-1] = weekSum.d;
console.log('tallys are ', tallys);
})
};
So what I would EXPECT here is to end up with something like this:
tallys = {
mikeduin: [-4.27, -1.41, 0, 0, 0 ... etc],
superbkn: [47.58, 14.06, 0, 0, 0 ... etc],
... etc
}
... with the appropriate values for each user. HOWEVER! This is what I end up with as my tallys object once all the loops etc have finished:
tallys are {
michaeljpow: [
-4.27, -1.41, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0
],
'Mr. Cheeseburger': [
-4.27, -1.41, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0
],
superbkn: [
-4.27, -1.41, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0
],
...etc
}
.... etc, but for every single user. It's assigning EVERY user the exact same value over and over again -- they all end up with -4.27 and -1.41 just because that was the last 'd' value that got looped through.
Why is it updating every username with the last relevant values when I have tallys[weekSum.username] in my code, so that it should only be updating a single username each time in the tallys object??
Thanks in advance for any help!
EDIT: Thank you again for everyone's help. #Bergi's answer in the comments is correct. When I edit my initial code that creates 'tallys' as he suggests like so -- everything works as it should. #vothanhdat's approach that I marked as the suggested answer in which I clone the initial 'weeks' array also solves the problem.
let tallys = {};
users.forEach(user => {
let weeks = [];
for (let i=0; i < maxWeek+1; i++) {
weeks.push(0)
};
tallys[user] = weeks;
});
Your problem is every tallys[user] reference to the same weeks array.
Example:
let a = [1,2,3]
console.log(a) // [1,2,3]
let b = a // now a & b is reference to the same array
b[0] = 100
console.log(a) // [100,2,3]
So the solution is clone array week for every user
const maxWeek = 25;
let weeks = [];
for (let i = 0; i < maxWeek + 1; i++) {
weeks.push(0)
};
let tallys = {};
users.forEach(user => {
tallys[user] = [...weeks] //Clone week array
});
I have this code
for (var i = 0; i < vm.items.users.data.length; i++) {
var user = vm.items.users.data[i];
user.goals_by_brands = [];
var brands = [];
vm.items.brands.data.forEach( function(element, index) {
brands.push(element);
});
console.log("brands", brands)
console.log("vm.items.brands.data", vm.items.brands.data)
brands.forEach( function(brand) {
brand.goals_by_months = [];
brand.user = user;
constants.MONTHS.forEach( function(month) {
brand.goals_by_months.push({goals: [], total_month_goal: 0, total_month_accumulated: 0});
});
user.goals_by_brands.push(brand);
});
}
I put this lines :
var brands = [];
vm.items.brands.data.forEach( function(element, index) {
brands.push(element);
});
But I tried too with clone array (slice() function) and it do the same.
In brands array and in vm.items.brands.data array, appeared the same; the last user in vm.items.users.data array.
I dont know why..
I would like to do this:
I have array with users. -> vm.items.users.data
I have array with brands. -> vm.items.brands.data
I have array with months. -> constants.MONTHS
I would like to add array with this object -> {goals: [], total_month_goal: 0, total_month_accumulated: 0} to each brand 12 times (one each month).
Then this brands, I would like to add to each user ->
[
{
id: "user1",
name: "user1",
goals_by_brands: [
{
id: "brand1",
name: "brand1",
goals_by_months: [
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0},
{goals: [], total_month_goal: 0, total_month_accumulated: 0}
]
}
]
}]
So I would like to add user into each brand object of goals_by_brands.
Sorry about my english.
So the problem with your code is that you have the "brands" references rather than a copy of brands. Since you are changing the main reference, the brands keeps getting over written, hence please make this change in your loop.
var brands = [];
vm.items.brands.data.forEach( function(element, index) {
brands.push(element); //This pushes the reference which remains the same.
});
change this push line to
var newBrand = JSON.parse(JSON.stringify(element))) //Make a deep copy of the element
brands.push(newBrand)