javascript - merge, combine, transform 2 different arrays of Objects - javascript

I can't figure it out how to transform and combine 2 arrays of object.
I have this 2 arrays of objects:
const selectedCourse = [
{
"courseType": [5],
"id": 26,
"title": "Apple Tart with Apricot Glaze",
},
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
},
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
]
const courseTypes = [
{name: "Hors d'oeuvres", id: 0},
{name: "Soup", id: 1},
{name: "Fish", id: 2},
{name: "Salad", id: 3},
{name: "Main course", id: 4},
{name: "Dessert", id: 5}
]
The courseType property inside the first JSON is an array of numbers that corresponds to courseTypes index and property id in the second JSON.
The result for this case should be this:
const result = [
{
courseType: 1,
courseName: "Soup",
courses: [
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
}
]
},
{
courseType: 3,
courseName: "Salad",
courses: [
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
}
]
},
{
courseType: 3,
courseName: "Fish",
courses: [
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
{
"courseType": [3],
"id": 16,
},
]
},
{
courseType: 5,
courseName: "Main course",
courses: [
{
"courseType": [5],
"id": 26,
"title": "Apple Tart with Apricot Glaze",
}
]
}
]
The expected result have to combine the 2 arrays by filtering by courseType property.

Assuming, you want all items with selectedCourse, you could take a Map and collect all courses and later greate a new array out of the found values.
This solution includes Fish as well.
const
selectedCourse = [{ courseType: [5], id: 26, title: "Apple Tart with Apricot Glaze" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }, { courseType: [1, 2], id: 10, title: "Lobster Bisque" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }],
courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }],
map = selectedCourse.reduce((m, o) => o.courseType.reduce((n, id) => n.set(id, [...(n.get(id) || []), o]), m), new Map),
result = courseTypes.reduce(
(r, { name: courseName, id: courseType }) => (map.get(courseType) || []).reduce((s, courses) => s.concat({ courseType, courseName, courses }), r),
[]
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You could use map and filter like this:
const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ]
const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ];
const result = courseTypes.map(courseType => ({
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(course => course.courseType.includes(courseType.id))
})).filter(extended => extended.courses.length);
console.log(JSON.stringify(result, null, 2));
Explanation:
courseTypes.map iterates over your second input array and for each type it finds in selectedCourse which courses match with that particular type.
It uses .filter to collect those matches. The filter callback uses includes to determine if there is a match -- it returns a boolean, exactly what the filter callback expects as return value.
This filtered array is then added to an object literal that also defines the other two properties courseType and courseName. That new object is what the course type is mapped to. courseTypes.map returns an array of those objects.
Finally that result may have entries that have an empty courses array. Those are filtered out with another call to .filter. If the length of that courses array is non zero, the object is kept, otherwise it is kicked out of the result.
For older browsers
Here is the same code made compatible with older browsers (no arrow functions, no includes, which were introduced in ES2015):
const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ]
const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ];
const result = courseTypes.map(function (courseType) {
return {
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(function (course) {
return course.courseType.indexOf(courseType.id) > -1;
})
};
}).filter(function (extended) {
return extended.courses.length;
});
console.log(JSON.stringify(result, null, 2));

while "trincot" code is work fine for chrome and Mozila but it will not work in IE edge and IE 10 and below you need to convert it in pure javascript. below is code which will work in all browser.
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
if (sameValueZero(o[k], searchElement)) {
return true;
}
// c. Increase k by 1.
k++;
}
// 8. Return false
return false;
}
});
}
var selectedCourse = [{ "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }, { "courseType": [1, 2], "id": 10, "title": "Lobster Bisque" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }];
var courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }];
var result = courseTypes.map(function (courseType) {
return {
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(function (course) {
return course.courseType.includes(courseType.id);
})
};
}).filter(function (extended) {
return extended.courses.length;
});
console.log(JSON.stringify(result, null, 2));

Related

Looping nested arrays get the sum in JavaScript

I am working on a Javascript array where I need to loop the 2nd array in the main array and get the total sum of a value of a particular field. below is what my JSON looks like. here I need to loop Array and get the sum of ps_lessons.lesson_length_minutes I need the O/P as 118 (20 + 22 + 33 + 43)
[
{
"sort_id": 1,
"category": "Introduction",
"ps_lessons": [
{
"id": "48ca672b-aaca-473c-b54b-3cf699da848b",
"sort_id": 1,
"lesson_title": "Welcome to the course",
"lesson_length_minutes": 20
},
{
"id": "3f0f5715-a442-4262-ad32-6fb653df62c2",
"sort_id": 2,
"lesson_title": "What is React JS?",
"lesson_length_minutes": 22
}
]
},
{
"sort_id": 2,
"category": "Fundamentals",
"ps_lessons": [
{
"id": "e28abd67-29a4-4bc9-a415-fb5db0aabfa9",
"sort_id": 4,
"lesson_title": "Fundamentals of React JS",
"lesson_length_minutes": 33
},
{
"id": "1d9668da-94e6-4085-bd89-176cc4e8e62d",
"sort_id": 3,
"lesson_title": "Fundamentals of JSX",
"lesson_length_minutes": 43
}
]
}
]
I tried something like the below by using the array method map 2 times but it's not working. can anyone suggest how to do this?
const extract_mins_and_sum = (result) => {
console.log('result', result);
result.map((single_row) =>
let sum = 0;
single_row.ps_lessons.map((single_row_lesson) =>
( console.log(single_row_lesson.lesson_length_minutes);
sum += single_row_lesson.lesson_length_minutes)
)
);
};
Thanks
Venk
You can try map, flat and reduce.
const extract_mins_and_sum = (result) => {
return result.map(x => x.ps_lessons.map(y => y.lesson_length_minutes)).flat().reduce((a, b) => a + b, 0)
};
The straightforward way is to loop through each element of the big array and get the sum by using a reduce function on each ps_lessons array.
const extract_mins_and_sum = (result) => {
let sum = 0;
result.forEach((elem) => {
sum += elem.ps_lessons.reduce((acc, val) => acc + val.lesson_length_minutes, 0);
});
return sum;
}
Map is generally used to map an array to another array, but preserving metadata like array length, order etc.
Reduce is generally used to, well, reduce an array to a single value, based on whatever logic you use in the callback function. On this example, reduce is used to transform an array into a sum of some numeric fields.
You could use a solution using map and reduce extracting the value to an external variable like so:
const data = [
{
sort_id: 1,
category: "Introduction",
ps_lessons: [
{
id: "48ca672b-aaca-473c-b54b-3cf699da848b",
sort_id: 1,
lesson_title: "Welcome to the course",
lesson_length_minutes: 20,
},
{
id: "3f0f5715-a442-4262-ad32-6fb653df62c2",
sort_id: 2,
lesson_title: "What is React JS?",
lesson_length_minutes: 22,
},
],
},
{
sort_id: 2,
category: "Fundamentals",
ps_lessons: [
{
id: "e28abd67-29a4-4bc9-a415-fb5db0aabfa9",
sort_id: 4,
lesson_title: "Fundamentals of React JS",
lesson_length_minutes: 33,
},
{
id: "1d9668da-94e6-4085-bd89-176cc4e8e62d",
sort_id: 3,
lesson_title: "Fundamentals of JSX",
lesson_length_minutes: 43,
},
],
},
];
const sumMinutes = (lessons) => {
return lessons.reduce((acc, ps) => {
return (acc + (ps.ps_lessons ? sumMinutes(ps.ps_lessons): ps.lesson_length_minutes));
}, 0);
};
console.log(sumMinutes(data))
You can use reduce function to solve this
const data = [
{
sort_id: 1,
category: "Introduction",
ps_lessons: [
{
id: "48ca672b-aaca-473c-b54b-3cf699da848b",
sort_id: 1,
lesson_title: "Welcome to the course",
lesson_length_minutes: 20,
},
{
id: "3f0f5715-a442-4262-ad32-6fb653df62c2",
sort_id: 2,
lesson_title: "What is React JS?",
lesson_length_minutes: 22,
},
],
},
{
sort_id: 2,
category: "Fundamentals",
ps_lessons: [
{
id: "e28abd67-29a4-4bc9-a415-fb5db0aabfa9",
sort_id: 4,
lesson_title: "Fundamentals of React JS",
lesson_length_minutes: 33,
},
{
id: "1d9668da-94e6-4085-bd89-176cc4e8e62d",
sort_id: 3,
lesson_title: "Fundamentals of JSX",
lesson_length_minutes: 43,
},
],
},
];
const sumMinutes = (lessons) => {
return lessons.reduce((acc, ps) => {
return (acc + (ps.ps_lessons ? sumMinutes(ps.ps_lessons): ps.lesson_length_minutes));
}, 0);
};
console.log(sumMinutes(data))

Constructing Tree View Object

I'd like to construct an Array Object for tree view in React Native.
Realm DB returns following rows as they have parent-child relation:
{
"0":{
"ID":3,
"name":"KITCHEN",
"parentID":2,
"createdBY":null,
"createdAT":null
},
"1":{
"ID":4,
"name":"BATHROOM",
"parentID":2,
"createdBY":null,
"createdAT":null
},
"2":{
"ID":5,
"name":"OIL",
"parentID":3,
"createdBY":null,
"createdAT":null
},
"3":{
"ID":6,
"name":"LIQUID",
"parentID":5,
"createdBY":null,
"createdAT":null
},
"4":{
"ID":7,
"name":"SOLID",
"parentID":5,
"createdBY":null,
"createdAT":null
}
}
Object should be look like this:
const treeData = [
{
key: 3,
label: 'KITCHEN',
nodes: [
{
key: '5',
label: 'OIL',
nodes: [
{
key: '6',
label: 'LIQUID',
},
{
key: '7',
label: 'SOLID',
},
],
},
],
},
{
key: 4,
label: 'BATHROOM',
},
];
My attempt was looping over all rows and get their IDs then in a nested loop checking the parentID with the ID and if any match occurs then adding that node to another object.
This only gives me the child/s of any parent.
for (var i = 0; i < rows.length; i++) {
let tempID = rows[i].ID
treeData = treeData.concat(rows[i])
for (var j = 0; j < rows.length; j++) {
let tempParentID = rows[j].parentID
if (tempID == tempParentID) {
subCategoryJson = subCategoryJson.concat(rows[j])
}
}
}
Problem is I am really not sure how to construct exactly the above Array Object.
PS. I'm trying to use following node module: https://www.npmjs.com/package/react-simple-tree-menu
You could store the keys and filter the parentt nodes for the result.
var data = { 0: { ID: 3, name: "KITCHEN", parentID: 2, createdBY: null, createdAT: null }, 1: { ID: 4, name: "BATHROOM", parentID: 2, createdBY: null, createdAT: null }, 2: { ID: 5, name: "OIL", parentID: 3, createdBY: null, createdAT: null }, 3: { ID: 6, name: "LIQUID", parentID: 5, createdBY: null, createdAT: null }, 4: { ID: 7, name: "SOLID", parentID: 5, createdBY: null, createdAT: null } },
tree = function (data) {
var t = {},
parents = {};
Object.values(data).forEach(({ ID: key, name: label, parentID }) => {
Object.assign(t[key] = t[key] || {}, { key, label });
t[parentID] = t[parentID] || { };
t[parentID].nodes = t[parentID].nodes || [];
t[parentID].nodes.push(t[key]);
parents[key] = true;
});
return Object
.keys(t)
.filter(k => !parents[k])
.flatMap(k => t[k].nodes);
}(data);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would first loop and create a look up object so it is easy to reference parents and check if a parent exists.
After that I would loop over the data again and check to see if it has a parent, if it does, add a nodes property and push the element to it. If not add to the parent node.
const data = {
"0": {
"ID": 3,
"name": "KITCHEN",
"parentID": 2,
"createdBY": null,
"createdAT": null
},
"1": {
"ID": 4,
"name": "BATHROOM",
"parentID": 2,
"createdBY": null,
"createdAT": null
},
"2": {
"ID": 5,
"name": "OIL",
"parentID": 3,
"createdBY": null,
"createdAT": null
},
"3": {
"ID": 6,
"name": "LIQUID",
"parentID": 5,
"createdBY": null,
"createdAT": null
},
"4": {
"ID": 7,
"name": "SOLID",
"parentID": 5,
"createdBY": null,
"createdAT": null
}
}
const values = Object.values(data)
const lookup = values.reduce((obj, entry) => ({
[entry.ID]: entry,
...obj
}), {})
const result = values.reduce((arr, entry) => {
const parent = lookup[entry.parentID]
if (parent) {
parent.nodes = parent.nodes || []
parent.nodes.push(entry)
} else {
arr.push(entry)
}
return arr
}, [])
console.log(result)

Mutate or Make a new Array by replacing a value

I have two arrays (and the length can be in 1000s):
I want my array to replace status to the status of array 2. Here is the output example:
[{
value: 123,
status: 'demo',
type: '...'
},
{value: 2335,
status: 'demo2',
type: 'xxx'
}]
As we can see it needs to get the status from another array and replace it. What are the most possible efficient solutions for this? As this array can be very large. I don't know a good approach to solve this problem.
Length and sort order can be different, I need to replace array1's status by the array2's status,
By linking Array1's status and Array2's id
My actual Data
[
{
"id": "55",
"status": "2",
"type": "COD",
"value": "5038.2",
},
{
"id": "56",
"status": "2",
"type": "COD",
"value": "5398.2",
},
{
"id": "57",
"status": "2",
"type": "COD",
"value": "10798.2",
}
]
Array 2
[
{
"id": "1",
"status": "Awaiting Confirmation",
},
{
"id": "2",
"status": "Confirmed",
},
{
"id": "3",
"status": "Awaiting Shipment",
},
{
"id": "4",
"status": "Awaiting Pickup",
},
{
"id": "5",
"status": "Shipped",
},
{
"id": "6",
"status": "Delivered",
},
{
"id": "7",
"status": "Cancelled",
},
{
"id": "8",
"status": "Refund Requested",
},
{
"id": "9",
"status": "Refunded",
}
Things i have tried...I have used lodash and a for loop to achieve this
const output = [];
for (let i = 0; i < array1.length; i++) {
const statuscode = array1[i].status;
const result = _.find(array2, { id: statuscode });
output.push({
value: array1[i].value,
status: result.status,
type: array1[i].type
});
}
console.log(output);
For high performance, transform one of the arrays to a Map first. Map lookups are very efficient:
const input1 = [{
value: 123,
status: 1,
type: 'COD',
},
{
value: 2335,
status: 2,
type: 'COD',
},
{
value: 222,
status: 3,
type: 'COD',
}
];
const input2 = [{
id: 1,
status: 'demo'
},
{
id: 2,
status: 'demo2'
}, {
id: 3,
status: 'demo3'
}
];
const map2 = new Map(Object.values(input2).map(({ id, status }) => [id, status]));
const output = input1.map(({ status, ...rest }) => {
const otherStatus = map2.get(status);
return { ...rest, status: otherStatus };
});
console.log(output);
Code readability generally matters more than speed, but if you wanted, you could transform the .map transformation into a for loop as well:
const input1 = [{
value: 123,
status: 1
},
{
value: 2335,
status: 2
},
{
value: 222,
status: 3
}
];
const input2 = [{
id: 1,
status: 'demo'
},
{
id: 2,
status: 'demo2'
}, {
id: 3,
status: 'demo3'
}
];
const map1 = new Map(Object.values(input1).map(({ value, status }) => [status, value]));
const output = [];
for (let i = 0; i < input2.length; i++) {
const { id, status } = input2[i];
output.push({ value: map1.get(id), status });
}
console.log(output);
A simple for loop would do:
for (let i = 0; i < array1.length; i++) {
array1[i].status = array2[i].status;
}
This of course assumes that the length and the order of the two arrays is the same.
EDIT
Alternative solution using Array.prototype.find and taking into account different lengths and orders.
for (let i = 0; i < array1.length; i++) {
const buffer = array1[i];
buffer.status = array2.find(x => x.id === buffer.status).status;
}
Also, I would highly recommend giving priority to readability over premature optimisation

Normalizr with nested array of objects

I have a nested array of objects like this:
var matchs = [
{
id: 10689,
sport: 'Tennis',
players: [
{
id: 22,
name:'Rafa Nadal',
country: 'Spain',
odds: [
{id: 1, bookie_1: 1.60},
{id: 2, bookie_2: 1.61},
{id: 3, bookie_3: 1.62},
]
},
{
id: 23,
name:'Roger Federer',
country: 'Spain',
odds: [
{id: 4, bookie_1: 2.60},
{id: 5, bookie_2: 2.61},
{id: 6, bookie_3: 2.62},
]
}
]
},
{
id: 12389,
sport: 'Tennis',
players: [
{
id: 45,
name:'Fernando Verdasco',
country: 'Spain',
odds: [
{id: 7, bookie_1: 2.60},
{id: 8, bookie_2: 2.61},
{id: 9, bookie_3: 2.62},
]
},
{
id: 65,
name:'Andy Murray',
country: 'Spain',
odds: [
{id: 10, bookie_1: 1.60},
{id: 11, bookie_2: 1.61},
{id: 12, bookie_3: 1.62},
]
}
]
}
];
I want to use normalizr to simplify array and use with redux. I have read the Normalizr documentation but it has few examples and I do not know what I am doing wrong.
I have tried the following code without success. The result I get is an array with undefined.
import { normalize, schema } from 'normalizr';
const match = new schema.Entity('matchs');
const player = new schema.Entity('players');
const odd = new schema.Entity('odds');
match.define({
player: [player],
odd: [odd]
});
console.log(normalize(matchs, [match]));
I need something like this:
{
result: "123",
entities: {
"matchs": {
"123": {
id: "123",
players: [ "1","2" ],
odds: [ "1", "2" ]
}
},
"players": {
"1": { "id": "1", "name": "Rafa Nadal" },
"2": { "id": "2", "name": "Andy Murray" }
},
"odds": {
"1": { id: "1", "bookie_1": "1.20" }
"2": { id: "2", "bookie_2": "1.21" }
"3": { id: "3", "bookie_3": "1.22" }
}
}
}
I cannot find a straight solution using only normalizr, so my only choice is to pre-format the data before passing to the normalizer.
const preformattedData = data.map(sport => {
const oddArrays = sport.players.map(player => player.odds || []);
return {
...sport,
odds: [].concat.apply([], oddArrays)
}
})
const odd = new schema.Entity('odds')
const player = new schema.Entity('players',
{
odds: [ odd ]
}
)
const sport = new schema.Entity('sports',
{
players: [ player ],
odds: [odd]
}
)
const normalizedData = normalize(preformattedData, [ sport ]);
Demo: https://codesandbox.io/s/20onxowzwn
I think this is what you need
const odd = new schema.Entity('odds');
const player = new schema.Entity('players' , { odds: [ odd]});
const match = new schema.Entity('matchs', {players: [player]});
but the result will be different because your json it is structured like this, I mean, the odds key is child of players, not of matches, therefore the result will be this way.
Just take a look at the console
Here is a solution with latest version of normalizr
const odds = new schema.Entity("odds");
const players = new schema.Entity("players", {
odds: [odds]
});
const matches = new schema.Entity("matches", { players: [players] });
const normalizedData = normalize(data, [matches]);
It would group data in your question as
{
"entities": {
"odds": {
"1": {
"id": 1,
"bookie_1": 1.6
}
},
"players": {
"22": {
"id": 22,
"name": "Rafa Nadal",
"country": "Spain",
"odds": [
1,
2,
3
]
}
},
"matches": {
"10689": {
"id": 10689,
"sport": "Tennis",
"players": [
22,
23
]
}
}
},
"result": [
10689
]
}
You can achieve your desired result by tweaking the process and merge strategies. I don't have time to do the leg work for you, but I explain the approach in detail here:
https://medium.com/#JustinTRoss/normalizing-data-into-relational-redux-state-with-normalizr-47e7020dd3c1

Slice properties from objects and counting

Is it possible to slice single property from array of objects like
[{"name":"Bryan","id":016, "counter":0}, {"name":"John","id":04, "counter":2}, {"name":"Alicia","id":07, "counter":6}, {"name":"Jenny","id":015, "counter":9}, {"name":"Bryan","id":016, "counter":0}, {"name":"Jenny","id":015, "counter":9}, {"name":"John","id":04, "counter":2}, {"name":"Jenny" ,"id":015, "counter":9}];
I'm trying to slice name from every object and count number of the same elements (there are 3 objects with name Jenny) in order to achieve the following structure:
[{"name":"Bryan","Number":2},
{"name":"John","Number":2},
{"name":"Alicia","Number":1},
{"name":"Jenny","Number":3}]
Do you want to ignore the id and counter props already present?
You could create an object to keep track of the unique names, and convert back to an array in the end:
var data = [{"name": "Bryan", "id": 016, "counter": 0}, { "name": "John", "id": 04, "counter": 2}, { "name": "Alicia", "id": 07, "counter": 6}, { "name": "Jenny", "id": 015, "counter": 9}, { "name": "Bryan", "id": 016, "counter ": 0}, { "name": "Jenny", "id": 015, "counter ": 9}, { "name": "John", "id": 04, "counter": 2}, { "name": "Jenny", "id": 015, "counter": 9}];
var result = data.reduce(function(result, item) {
if (!result[item.name]) {
result[item.name] = {
name: item.name,
counter: 0
};
}
result[item.name].counter += 1;
return result;
}, {});
console.log(Object.keys(result).map(function(key) { return result[key] }));
You could use a hash table as a reference to the counted names.
var data = [{ name: "Bryan", id: "016", counter: 0 }, { name: "John", id: "04", counter: 2 }, { name: "Alicia", id: "07", counter: 6 }, { name: "Jenny", id: "015", counter: 9 }, { name: "Bryan", id: "016", counter: 0 }, { name: "Jenny", id: "015", counter: 9 }, { name: "John", id: "04", counter: 2 }, { name: "Jenny", id: "015", counter: 9 }],
grouped = [];
data.forEach(function (a) {
if (!this[a.name]) {
this[a.name] = { name: a.name, Number: 0 };
grouped.push(this[a.name]);
}
this[a.name].Number++;
}, Object.create(null));
console.log(grouped);
Give this a shot. We create a dictionary of names with their counts called nameDict, and iterate through the list to count them.
var arr = [{"name":"Bryan","id":"016", "counter":0}, {"name":"John","id":"04", "counter":2}, {"name":"Alicia","id":"07", "counter":6}, {"name":"Jenny","id":"015", "counter":9}, {"name":"Bryan","id":"016", "counter":0}, {"name":"Jenny","id":"015", "counter":9}, {"name":"John","id":"04", "counter":2}, {"name":"Jenny","id":"015", "counter":9}];
var nameDict = {};
for(var i = 0; i < arr.length; i++)
{
var name = arr[i].name;
if(nameDict[name] == undefined){
//haven't encountered this name before so we need to create a new entry in the dict
nameDict[name] = 1
} else {
//otherwise increment the count
nameDict[name] += 1
}
}
console.log(JSON.stringify(nameDict));

Categories

Resources