Change structure of existing array - javascript

Hi I want to convert an array into another structure. Here is the original array.
[{"level1_label":"Branch 1","data":[{"count":"3","level2_label":"2021-11-11"}]},{"level1_label":"branch 2","data":[{"count":"1","level2_label":"2021-11-25"}]}]
I want to convert this array into
[
['Branch 1', '3', 2021 - 11 - 11],
['branch 2', '1', 2021 - 11 - 25]
];

Instead of using map I would suggest just iterating:
const data = [{
"level1_label": "Branch 1",
"data": [{
"count": "3",
"level2_label": "2021-11-11"
}]
}, {
"level1_label": "branch 2",
"data": [{
"count": "1",
"level2_label": "2021-11-25"
}]
}];
const result = [];
data.forEach(l1 => {
const lev2Arr = [l1.level1_label];
l1.data.forEach(l2 => {
lev2Arr.push(l2.count);
lev2Arr.push(l2.level2_label);
});
result.push(lev2Arr);
});
console.log(result);

Related

How to merge data from nested object to one array (using map) [duplicate]

This question already has answers here:
Flatten array of objects of arrays JavaScript
(6 answers)
How to do equivalent of LINQ SelectMany() just in javascript
(11 answers)
Merge arrays from object property in an object array [closed]
(3 answers)
Closed 1 year ago.
I know it is probably very simple, but i can't figure it out since 2 days.
{
"users": [
{
"id": 1,
"name": "Example1",
"data": [{data: "data1"}, {data:"data2"}]
},
{
"id": 2,
"name": "Example2",
"data": [{data: "data3"}, {data:"data4"}]
}
]
}
I want to merge all data's arrays into one.
I tried in many ways, for example like this, but it's not what i want.
let arr = [];
users.map(el => {
return arr.push([].concat([...el.data]))
})
console.log(arr)
what i want is that :
arr = [{data: "data1"}, {data:"data2"}, {data: "data3"}, {data:"data4"}]
If someone is able to help me I will be extremely grateful.
You can apply a .flat() at the end:
let obj = {
"users": [
{
"id": 1,
"name": "Example1",
"data": [{data: "data1"}, {data:"data2"}]
},
{
"id": 2,
"name": "Example2",
"data": [{data: "data3"}, {data:"data4"}]
}
]
};
let photos = obj.users.map(({ data }) => [].concat(data)).flat();
console.log(photos);
Just map over the array and use flat on the result.
const obj = {
users: [{
id: 1,
name: "Example1",
data: [{
data: "data1"
}, {
data: "data2"
}],
},
{
id: 2,
name: "Example2",
data: [{
data: "data3"
}, {
data: "data4"
}],
},
],
};
const result = obj.users.map((o) => o.data).flat();
console.log(result);
or just use flatMap
const obj = {
users: [{
id: 1,
name: "Example1",
data: [{
data: "data1"
}, {
data: "data2"
}],
},
{
id: 2,
name: "Example2",
data: [{
data: "data3"
}, {
data: "data4"
}],
},
],
};
const result = obj.users.flatMap((o) => o.data);
console.log(result);

How to group from array object

I using code form "
I am looking for best ways of doing this. I have group:
data
[
{
"date": "16/04/2020",
"count": 0,
"name": "A"
},
{
"date": "16/04/2020",
"count": 1,
"name": "B"
},
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
//...More.....
]
Answer
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": [
{
"date": "16/04/2020",
"count": 0,
"name": "A"
}
]
},
{
"name": "B",
"count": [
{
"date": "16/04/2020",
"count": 1,
"name": "B"
}
]
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count": [
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
]
},
//...More.....
]
}
]
}
}
Can I fix the code and to get the desired answer?
Code :
const items = [
{
tab: 'Results',
section: '2017',
title: 'Full year Results',
description: 'Something here',
},
{
tab: 'Results',
section: '2017',
title: 'Half year Results',
description: 'Something here',
},
{
tab: 'Reports',
section: 'Marketing',
title: 'First Report',
description: 'Something here',
}
];
function groupAndMap(items, itemKey, childKey, predic){
return _.map(_.groupBy(items,itemKey), (obj,key) => ({
[itemKey]: key,
[childKey]: (predic && predic(obj)) || obj
}));
}
var result = groupAndMap(items,"tab","sections",
arr => groupAndMap(arr,"section", "items"));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ref : Group array of object nesting some of the keys with specific names
But I would like to have the answer line this (Answer) :
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": 0,
},
{
"name": "B",
"count": 1,
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count":0,
},
//...More.....
]
}
]
}
}
Thanks!
I am a beginner but it looks like you want system.data.data to = an array of objects with the keys name:str and count:number but instead you are applying the whole object into count so the key count:{name:A, count:0,date:etc}.
I really can't follow your function which separates the data... but all you should have to do is when count is sent the object to reference just do a dot notation like object.count to access the number vs the object that way you will have the desired affect. Hopefully that is what you were asking.
I would use a helper function groupBy (this version is modeled after the API from Ramda [disclaimer: I'm one of its authors], but it's short enough to just include here.) This takes a function that maps an object by to a key value, and then groups your elements into an object with those keys pointing to arrays of your original element.
We need to use that twice, once to group by month and then inside the results to group by day. The rest of the transform function is just to format your output the way I think you want.
const groupBy = (fn) => (xs) =>
xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})
const transform = (data) =>
Object .entries (groupBy (({date}) => date.slice(3)) (data)) // group by month
.map (([date, data]) => ({
date,
symtom: {
data: Object .entries (groupBy (({date}) => date) (data)) // group by day
.map (([date, data]) => ({
date,
data: data .map (({date, ...rest}) => ({...rest})) // remove date property
}))
}
}))
const data = [{date: "16/04/2020", count: 0, name: "A"}, {date: "16/04/2020", count: 1, name: "B"}, {date: "17/04/2020", count: 0, name: "B"}, {date: "03/05/2020", count: 0, name: "C"}];
console .log (
transform (data)
)
.as-console-wrapper {min-height: 100% !important; top: 0}
If you need to run in an environment without Object.entries, it's easy enough to shim.
You could take a function for each nested group and reduce the array and the grouping levels.
var data = [{ date: "16/04/2020", count: 0, name: "A" }, { date: "16/04/2020", count: 1, name: "B" }, { date: "17/04/2020", count: 0, name: "B" }],
groups = [
(o, p) => {
var date = o.date.slice(3),
temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, symptom: { data: [] } });
return temp.symptom.data;
},
({ date }, p) => {
var temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, data: [] });
return temp.data;
},
({ date, ...o }, p) => p.push(o)
],
result = data.reduce((r, o) => {
groups.reduce((p, fn) => fn(o, p), r);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript compare two JSON arrays and return key of the unmatched value

I have two JSON arrays, would like to know the key which don't match. I don't need the value.
Example:
livetable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" },
],
backupTable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" },
],
I can get the key/value pair which is diffrent with this Lodash script:
difference = _.differenceWith(livetable,backupTable,_.isEqual)
But I would just need the key, in this example "name" for "id: 2" is not matching, so I would need to get the "name" key to new array/variable.
(Using VUE CLI)
EDIT: Added example of current code output.
var livetable = [{"id": 1, "name": "Sandra", "id": 2, "name": "John"}]
var backupTable = [{"id": 1, "name": "Sandra", "id": 2, "name": "Peter"}]
console.log(_.differenceWith(backupTable,livetable,_.isEqual))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
This will output the key:value pair, but I would just need the key which is diffrent.
I think I understand what you're trying to do. There are some unknowns though, like what should happen if there is a missing record in the second data set?
This solution assumes each table of data has the same amount of records and the records have the same IDs.
// define data
const livetable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" }
]
const backupTable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" }
]
const getDifferentRecordsByID = (sourceRecords, compareRecords) => {
// simple utility function to return a record object matching by ID
const findComparisionRecord = id => compareRecords.find(compareRecord => compareRecord.id === id)
// using the utility function, we can filter out any mismatching records by comparing name
return sourceRecords
.filter(sourceRecord => sourceRecord.name !== findComparisionRecord(sourceRecord.id).name)
// then map over all the records and just pull out the ID
.map(record => record.id)
}
console.log(getDifferentRecordsByID(livetable, backupTable)) // [2]
Here is working VUE code for my problem.
Function returns [ "name" ], which is exactly what I need.
data() {
return {
livetable: [{ id: 1, name: "Sandra" },{ id: 2, name: "John" }],
backupTable: [{ id: 1, name: "Sandra" },{ id: 2, name: "Peter" }],
difColumns: null,
};
},
methods: {
test3() {
let resultArray = []
this.livetable.forEach((array1, index) => {
const array2 = this.backupTable[index];
resultArray.push(this._.reduce(array1, (result, value, key) => this._.isEqual(value, array2[key]) ? result : result.concat(key), []))
});
this.difColumns = resultArray[0]
}
},

Array Sort by time hh:mm:ss

I am trying to sort the time. but I am unable to sort by time (hh:mm:ss) format. so i have used moments js. my array sort by time not get sorted. how sort array by using maps
I have an array of objects:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e =>[["id", "date"],[e.id, moment(e.date, 'hh:mm:ss')]])
);
elements.sort((a, b) => parsedDates.get(a) - parsedDates.get(b));
console.log(elements.map(e => ({ id: e.id, date: e.date })));
You can lexicographical sort the time using string.localeCompare().
let times = [ { "id": 1, "date": "02:01:02" }, { "id": 2, "date": "01:01:01" }, { "id": 3, "date": "03:01:01" }, { "id": 4, "date": "04:01:01" } ];
times.sort((a,b) => a.date.localeCompare(b.date));
console.log(times);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try this
function convertDateObj(hhmmss){
let obj = new Date();//creates a Date Object using the clients current time
let [hours,minutes,seconds] = hhmmss.split(':');
obj.setHours(+hours); // set the hours, using implicit type coercion
obj.setMinutes(minutes); //you can pass Number or String, it doesn't really matter
obj.setSeconds(seconds);
return obj;
}
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
elements.sort((a, b) => convertDateObj(a.date) - convertDateObj(b.date)); // Ascending order
elements.sort((a, b) => convertDateObj(b.date) - convertDateObj(a.date)); // Descending order
The parsedDates map you've created is looking like:
Map {
[ 'id', 'date' ] => [ 1, <some Date object> ],
[ 'id', 'date' ] => [ 2, <some Date object> ],
[ 'id', 'date' ] => [ 3, <some Date object> ],
[ 'id', 'date' ] => [ 4, <some Date object> ]
}
And then you try to extract from it with elements like this:
parsedDates.get({ "id": 1, "date": "02:01:02" })
This should not work, because the key in a Map is and Array instance.
Even if you were using an array as a key:
parsedDates.get([ 1, "02:01:02" ])
this still wouldn't work, as this would be a different Object reference. I mean two arrays
a = [ 1, "02:01:02" ]
b = [ 1, "02:01:02" ]
are stored in different places and are different Objects, even though their values are identical.
So, you can modify your solution a bit:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e => [e.date, e])
);
elements = elements.map(x => x.date).sort().map(x => parsedDates.get(x))
console.log(elements)
// [
// { id: 2, date: '01:01:01' },
// { id: 1, date: '02:01:02' },
// { id: 3, date: '03:01:01' },
// { id: 4, date: '04:01:01' }
// ]

Javascript filter an array with another array of elements

I want to implement a tag filter for a search and get an array of entries (variable: entries) like this with many entries:
"entries":[
{
"id":1,
"details":"text",
"tags":[
{
"id":9,
"label":"Label9"
},
{
"id":6,
"label":"Label6"
},
],
"date":"Mar 8, 2018 2:45:30 PM"
}]
I want to filter this array with another array of tags (variable: tags) like this:
"tags":[
{
"id":6,
"label":"Label6"
}
At the end I need an array of those entries which contain all tags in the tags array. ]
I wrote this code but something is wrong. It compares the id of each tag.
const entries = [{
"id": 1,
"details": "text",
"tags": [{
"id": 9,
"label": "Label9"
},
{
"id": 6,
"label": "Label6"
},
],
"date": "Mar 8, 2018 2:45:30 PM"
}]
const tags = [{
"id": 6,
"label": "Label6"
}]
function containSearchTag(tags) {
return entries.filter(function(el) {
for (let i = 0; i < el.tags.length; i++) {
for (let j = 0; j < tags.length; j++) {
return el.tags[i].id === tags[j].id;
}
}
});
}
console.log(containSearchTag(tags));
You could use a Set and filter the array by checking the tags array with the set.
var entries = [{ id: 1, details: "text", tags: [{ id: 9, label: "Label9" }, { id: 6, label: "Label6" }], date: "Mar 8, 2018 2:45:30 PM" }],
tags = [{ id: 6, label: "Label6" }],
ids = new Set(tags.map(({ id }) => id)),
result = entries.filter(({ tags }) => tags.some(({ id }) => ids.has(id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use of Array.some to make it easier; like :
const entries = [{
id: 1,
details: 'text',
tags: [{
id: 9,
label: 'Label9'
},
{
id: 6,
label: 'Label6',
},
],
date: 'Mar 8, 2018 2:45:30 PM',
}, {
id: 1,
details: 'text',
tags: [{
id: 9,
label: 'Label9',
},
{
id: 12,
label: 'Label12',
},
],
date: 'Mar 8, 2018 2:45:30 PM',
}];
function filterByTag(tags) {
return entries.filter(x => x.tags.some(y => tags.some(z => z.id === y.id)));
}
console.log(filterByTag([{
id: 6,
label: 'Label6',
}]).length);
console.log(filterByTag([{
id: 9,
label: 'Label6',
}]).length);
console.log(filterByTag([{
id: 17,
label: 'Label6',
}]).length);
Use Array.filter, Array.every and Array.some
let entries = [{"id":1,"details":"text","tags":[{"id":9,"label":"Label9"},{"id":6,"label":"Label6"},],"date":"Mar 8, 2018 2:45:30 PM"}];
let tag = [{"id":6,"label":"Label6"}];
// Create an array of unique id's
let ids = tag.map(({id}) => id);
// filter only those entries which have all the tag ids specified in tag array
let result = entries.filter(({tags}) => ids.every((id) => tags.some((tag) => tag.id === id)));
console.log(result);
Try This I hope it will help you
var data = JSON.parse('{"entries":[{"id":1,"details":"text","tags":[{"id":9,"label":"Label9"},{"id":6,"label":"Label6"}],"date":"Mar 8, 2018 2:45:30 PM"}]}');
let tag = JSON.parse('[{"id":6,"label":"Label6"}]');
data.entries.forEach((element)=>{
element.tags.forEach((value)=>{
tag.forEach((find)=>{
if(find.id === value.id)
{
console.log("tag is avaliable ");
console.log(value);
}
});
});
});
An optimized solution can be to create a map of all the ids of tags present corresponding to each entry and than search for all the tag ids of the tag array. Search in map can be done in O(1) time. which can help in reducing the overall time complexity.
var entries = [{"id":1,"details":"text","tags":[{"id":9,"label":"Label9"},{"id":6,"label":"Label6"}],"date":"Mar 8, 2018 2:45:30 PM"}];
var tags =[{"id":6, "label":"Label6"}];
var result = entries.filter((obj) => {
var tagMap = obj.tags.reduce((a, o) =>{ a[o.id] = true; return a;}, {});
var bool = true;
tags.forEach((o) => {var x = tagMap[o.id] ? true : false; bool = bool && x;})
return bool;
});
console.log(result);

Categories

Resources