Populate array based on JSON object mapping - javascript

I have a requirement where I need to populate array based on mapping of JSON object.
For e.g:
Suppose I have JSON object as shown below:
let columns = { 'name' :'value', 'id' : 1, 'age': 15}
And I want to create an array having value as shown below:
var values = [1, 15, value]; // id, age, name
I was able to create array of array as shown below:
var data = new Array();
var output = new Array();
let columns = [
{ 'name' :'value', 'id' : 1, 'age': 15},
{ 'name' :'value1', 'id' : 2, 'age': 18}
];
for(let i=0;i< columns.length; i++) {
for (let variable in columns[i]) {
data.push(columns[i][variable]);
}
output.push(data);
data = new Array();
}
console.log(output);
I am struggling to push value to array in order which I need. I tried by creating a mapping object but no success so far. Please let me know possible solution.
EDIT:
Thanks for the solution is there any way by which I can define the map function arguments and json object in variable. And replace it. Something like shown below:
let mapping {
columns : '{name, id, age}',
mapping : '[id, age, name]'
}
const result = columns.map((mapping.columns) => mapping.mapping);

You can use map() method with ES6 parameter destructuring and add properties to array in order you want.
let columns = [{ 'name' :'value', 'id' : 1, 'age': 15},{ 'name' :'value1', 'id' : 2, 'age': 18}];
const result = columns.map(({name, id, age}) => [id, age, name]);
console.log(result)

You can also remove the inner for loop and read data with the column names (or the JSON field names), So it becomes as follows.
var data = new Array();
var output = new Array();
let columns = [
{ 'name' :'value', 'id' : 1, 'age': 15},
{ 'name' :'value1', 'id' : 2, 'age': 18}
];
for(let i=0;i< columns.length; i++) {
data.push(columns[i]['id']);
data.push(columns[i]['age']);
data.push(columns[i]['name']);
output.push(data);
data = new Array();
}
console.log(output);

you can use Object.values() to get the every values from the object
var output = new Array();
let columns = [
{ 'name' :'value', 'id' : 1, 'age': 15},
{ 'name' :'value1', 'id' : 2, 'age': 18}
];
output = columns.map(item => Object.values(item))
console.log(output);

Related

How to merge an array of objects into one array and then filter out the duplicates

Firstly, I am trying to merge an array of many objects into a single array with every key in each object.
Lastly, any duplicate items in the array should be removed as well as any elements named "name".
Input:
const data = [
{
name: '10/20',
Tyler: 1,
Sonia: 0,
Pedro: 0,
},
{
name: '10/23',
Tyler: 0.5,
Sonia: 0.25,
Pedro: 0.75,
George: 0.5,
},
];
Output:
["Tyler", "Sonia", "Pedro", "George"]
This is what I've tried so far:
const mergedData = data.reduce((prev, cur) => {
const obj = cur[0];
const keys = Object.keys(obj);
const names = keys.splice(1);
return { names };
}, []);
I am trying to capture any key name other than "name" and add it to the final array. However, this is where I get stuck because I get this error, TypeError: Cannot convert undefined or null to object
Note: Objects may be different lengths, contain a mix of names, but never any duplicates.
An option is to find all keys put in a set and remove the name key
const data = [
{
name: '10/20',
Tyler: 1,
Sonia: 0,
Pedro: 0,
},
{
name: '10/23',
Tyler: 0.5,
Sonia: 0.25,
Pedro: 0.75,
George: 0.5,
},
];
const set = new Set(data.reduce((acc, i) => [...acc, ...Object.keys(i)], []));
set.delete('name');
const result = [...set];
console.log(result);
If you have access to ES6 methods, you can do this using a Set (unique values are ensured at creation) and converting it back into an array if you want through Destructuring.
data = [{name: '0', Tyler: '1', Dan: '2', Carl: '3'}, {name: '0', Tyler: '1', Dan: '2', Eric: '3', Danny: '4'}];
const output = (data) => {
let output = [];
// This makes sure you get each array and then strips just the keys as desired
data.forEach(item => {
output = output.
concat(Object.keys(item))
});
// This creates the set, strips our dups, and then spreads itself into an array
return [...new Set(output)]
// Strip out the 'name' key as needed
// NOTE: This should be a param instead of hard-coded, but this is easier to show
.filter(res => res != 'name');
}
console.log(output(data));
This should be fairly performant considering it only navigates the full array one time and each object itself shouldn't have millions of properties to cause .keys() any issues.

Object Array with dates, tallied together for each month

Overview
I need to make a chart in my react project.
Using data from a json (Object Array).
Example json:
[
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
]
Result object array structure required:
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [0,2,1,0,2,0,0,0,0,0,0,0,0,1,0,0,0,...] },
...]
// week_qty will be an array of 52 to represent each week of the year. It will be a 0 if there was no dates for that week.
Goal
This is what the new object array should look like, if we used the example json.
[
{name: "Aaron", recruiter_id:1, week_qty: [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Bob", recruiter_id:2, week_qty: [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Jane", recruiter_id:3, week_qty: [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]}
]
What I have
I dont have any working code yet. I am currently working on object[0] to attempt to put the dates into the 52 array. And then after that I will then turn it into a loop to work on each object. Once I have it semi working, I will post it for example.
--- Edit ---
var array = result
var flags = [], output = [], l = array.length, i;
for (i = 0; i < l; i++) {
if (flags[array[i].recruiter_id]) continue;
flags[array[i].recruiter_id] = true;
var temp = {}
temp.Recruiter_id = array[i].recruiter_id
temp.Name = array[i].name
temp.QTY = []
output.push(temp);
}
console.log("output : ", output)
This produces the new object array structure with the id and name filled out.
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [] },
...]
It only has 1 object for each id
Now I need to work on getting the week numbers for the dates and put them into each of those objects.
Question
Any code suggestions on how to get this result?
Side Note
If your curious to know how I then plan on using the new object array to use with my chart.
I will let the user select the week. Lets say week 1.
I will then map through the object array and get the week_qty for index 1 and the name value of the object.
I will store that week_qty and the name in a new new object array.
That new new object array will then look like this
[{name: "Aaron",QTY: 2},{name: "Bob",QTY: 1,]
That will then be passed as the x and y value to the chart.
You can use reduce and increase the week counter after parsing each date and getting the week (using moment.js for that part here)
But you can see Get week of year in JavaScript like in PHP for more details on how to calculate it yourself
const data = [
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
];
const weekly = data.reduce((acc, item, index, array) => {
const {
recruiter_id,
datetime_created,
name
} = item;
let existing = acc.find(({
recruiter_id: id
}) => id === recruiter_id);
if (!existing) {
existing = {recruiter_id, name, week_qty:Array(52).fill(0)};
acc.push(existing);
}
const week = moment(datetime_created,'D/M/YYYY').week()-1;
existing.week_qty[week]++;
return acc;
}, []);
console.log(JSON.stringify(weekly))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>

How can I know how many matches I have between two arrays (one nested inside an object)?

I need to know how many matches I have between people.compare array and names array, then create a new object including this data.
names = [ 'Juan', 'Old']
people = [
{compare: ['Juan', 'Old'], Age: 70},
{compare: ['Juan', 'Young'], Age: 20}
]
Expected output:
peopleNew = [
{compare: ['Juan', 'Old'], 'Age': 70, 'MATCHES': 2},
{compare: ['Juan', 'Young'], 'Age': 20, 'MATCHES': 1}
]
This code loops through each array and uses Array.includes() to check each item for equality:
const peopleNew = people.map(obj => {
let matches = 0;
obj.compare.forEach(name => {
if (names.includes(name)) {
matches++; // Increase count by 1
}
})
// Create new object from original with new 'matches' property
return Object.assign({}, obj, { matches });
});

How to chunk an array based on another array of numbers?

I have an array of data, and an array of objects:
const data = ['1', '2', '2'];
const objlist = [{name : 'dummy'} , {name: 'new'}, {name : 'news'}, {name : 'place'}, ...]; // 5 objects
I want to chunk the objects in objlist by the numbers in data so that I get the follow result:
result = [
[{name:'dummy'}],
[{name:'new'}, {name:'news'}],
[{name : 'place'}, ...]
]
As you can see, it should be of the form:
[[{obj1}], [{obj2}, {obj3}], [{obj4}, {obj5}]]
You could push sliced parts to the result.
let array = [1, 2, 2],
objlist = [{ name: 'dummy' }, { name: 'new' }, { name: 'news' }, { name: 'place' }, { name: 'place' }],
result = [],
i = 0,
j = 0;
while (j < array.length) {
result.push(objlist.slice(i, i += array[j++]));
}
console.log(result);
You can loop through your array of numbers and for each number n use .splice(0, n) to get an array chunk from your array of objects. This will modify the array in-place, allowing your next .splice() to get the next consecutive object. For each .splice() you perform, you can .push() this into a resulting array.
See example below:
function partition([...arr], chunks) {
const res = [];
for(const n of chunks)
res.push(arr.splice(0, n)); // +n to turn the string number into a number (splice will do this conversion for you but you can take care of it explicitly as well)
return res;
}
const chunkArr = ['1', '2', '2'];
const arr = [{ name : 'dummy' }, {name: 'new' }, { name : 'news'},{name : 'place'}, {name : 'foo'}];
console.log(partition(arr, chunkArr));
Above I'm using partition([...arr], chunks) which uses the destructuring assignment syntax to perform a shallow copy of your input array. This way when you modify it inside your function using .splice(), it won't change the passed-in array.

Extending objects in array without redefining

I've got an array of objects
var myArray = [{'id':'1','value':'firstValue'},{'id':'1','value':'secondValue'}, etc.]
I want to be able to extend the array later on in the code, so that I will have
var myArray = [{'id':'1','value':'firstValue', 'anothervalue':'anotherFirstValue'},{'id':'1','value':'secondValue', 'anothervalue':'anotherSecondValue'}, etc.]
Is there a way to do it without redefining myArray?
You can map the array, and add to each object:
var myArray = [{
'id': '1',
'value': 'firstValue'
}, {
'id': '1',
'value': 'secondValue'
}];
//later on
myArray = myArray.map(function(obj) {
obj.anothervalue = 'anotherFirstValue';
return obj;
});
console.log(myArray);

Categories