how to transform an array to object - javascript

I'm trying to filter an array of objects of people into a new object with its property names arranged by age each in a separate array.
Example 1
Input:
groupAdultsByAgeRange([{name: "Henry", age: 9}, {name: "John", age: 20}])
Result:
{ '20 and younger': [ { name: 'John', age: 20 } ] }
Example 2
Input:
groupAdultsByAgeRange([{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}])
Result:
{
'31-40': [ { name: 'Anna', age: 31 }, { name: 'John', age: 32 } ],
'51 and older': [ { name: 'Hank', age: 60 } ]
}
If the age range is not in the input than it should not be part of the output. For example if the input does not have people with age 51 than the object should not contain property of '51 and older'. and if input us empty array than output should be an empty object.

Using lodash you can do something like this
const _ = require('lodash');
const array = [{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}];
function ageToRange(obj) {
const age = obj.age;
if (age <= 20) {
return '20 and younger';
}
if (age > 30 && age <= 40) {
return '31-40'
}
if (age > 50) {
return '51 and older';
}
}
const result = _.groupBy(array, ageToRange)
console.log(result);

This is how you do with native Javascript :
//example 1
let people1 = [{name: "Henry", age: 9}, {name: "John", age: 20}]
let younger_and_equal_20 = []
people1.forEach(e => {
if(e.age>=20){
younger_and_equal_20.push(e)
}
});
console.log({"20 and younger": younger_and_equal_20})
//example 2
let people2 = [{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}]
let data = {
"31-40" : [],
"51 and older" : []
}
people2.forEach(e => {
if(e.age>30 && e.age<=40){
data["31-40"].push(e)
}
else if(e.age>50){
data["51 and older"].push(e)
}
});
console.log(data)

let result = {}
function groupAdultsByAgeRange(people) {
// An array of object which represents people who are 20 or younger
const ageGroup = people.filter(person => person.age <= 20)
// Only add array to the object key if it's not empty
if (ageGroup.length > 0) {
result["20 and younger"] = ageGroup
}
return result;
}

Related

Map + filter - Showing people that have < 18 years and abbreviate names

I wanted to be able to transform the age into a single array, so I would already know how to filter, then apply the mapping to only show people over 18 years old, in addition, to present the abbreviated names of the people.
Example:
name: "Raul", age: 27,
name: "Jose", age: 14,
name: "Maria", age: 52,
name: "Jesus", age: 17,
name: "Neo", age: 2
[Ra, Ma] -> Those are above 18, and their names go abbreviated
Here what i tried to do:
const amantesGatos = {
name: "Raul", age: 27,
name: "Jose", age: 14,
name: "Maria", age: 52,
name: "Jesus", age: 17,
name: "Neo", age: 2
};
// this needs to be filtered
const idade = amantesGatos.age
//i tried to destructuring this array
const nomeAbrev = [amantesGatos.map(n=>n[0] + n[1])]
//Tried to abbreviated names
//Filter above 18
const array = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 444, 17];
function above18(num) {
for (let i = 18; num < i; i--) {
if (num < i) {
return false;
}
}
return num;
}
console.log(array.filter(above18));
If I'm understanding correctly the desired outcome is [Ra, Ma]?
If so you can .filter.map.
const peeps = [
{name: "Raul", age: 27,},
{name: "Jose", age: 14,},
{name: "Maria", age: 52,},
{name: "Jesus", age: 17,},
{name: "Neo", age: 2}
]
const ofAgePeeps = peeps.filter(({age}) => age > 18)
const shortNames = ofAgePeeps.map(({name}) => name.substring(0,2))
You can also chain these...
peeps.filter(({age}) => age > 18).map(({name}) => name.substring(0,2))
That said your amantesGatos is an object with a bunch of duplicate keys and not an array. Which means it's really an object with only the last name and age. For example...
const obj = {
name: 'Tom', age: 2, name: 'Bob', age: 100
}
console.log(obj) // {name: 'Bob', age: 100}
You can do as following
let users = [
{ name: "Raul", age: 27,},
{name: "Jose", age: 14,},
{name: "Maria", age: 52,},
{name: "Jesus", age: 17,},
{name: "Neo", age: 2},
]
let data = users.filter(user => user.age > 18).map(user => user.name.slice(0, 2))
data would be [ 'Ra', 'Ma' ]

how to replace array of object with an object in javascript without repeating

let a = [{ name: "ben", age: 25 }, { name: "jeffrey", age: 10 },{ name: "daniel", age: 20 }]
let case1 = { name: "ben", age: 10 }
let case2={ name: "jack", age: 30 }
case1:
i expect the result to be
[{ name: "ben", age: 10 }, { name: "jeffrey", age: 10 },{ name: "daniel", age: 20 }]
where "ben" is existing so it replaces age to 10
case2:
i expect the result to be
[{ name: "ben", age: 25 }, { name: "jeffrey", age: 10 },{ name: "daniel", age: 20 },{ name: "jack", age: 30 }]
where "jack" is not there in the array so it adds to the array
how to write a function which does this functionality
Yours is a good case for Array.prototype.findIndex (MDN), which is like Array.prototype.find but returns the found index instead of the item.
let a = [{ name: "ben", age: 25 }, { name: "jeffrey", age: 10 },{ name: "daniel", age: 20 }]
let case1 = { name: "ben", age: 10 }
let case2 = { name: "jack", age: 30 }
const arrayUpsert = function (array, object) {
const objectIndex = array.findIndex(item => item.name == object.name)
if (objectIndex == -1) {
array.push(object)
} else {
array[objectIndex] = { ...array[objectIndex], ...object }
}
return array
}
console.log(arrayUpsert(a, case1))
console.log(arrayUpsert(a, case2))
/* [
{ name: 'ben', age: 10 },
{ name: 'jeffrey', age: 10 },
{ name: 'daniel', age: 20 }
]
[
{ name: 'ben', age: 10 },
{ name: 'jeffrey', age: 10 },
{ name: 'daniel', age: 20 },
{ name: 'jack', age: 30 }
] */
Can be done with a for loop as well.
function untitled(original, newObj) {
for (let index = 0; index < original.length; index++) {
if (original.name && newObj.name === a[index].name) {
original[index] = {...newObj};
console.log(original); return;
}
}
original.push(newObj); console.log(original);
}
let a = [{ name: "ben", age: 25 }, { name: "jeffrey", age: 10 },{ name: "daniel", age: 20 }]
let case1 = { name: "ben", age: 10 }
let case2 = { name: "jack", age: 30 }
untitled(a, case1);
untitled(a, case2);
I'm using ramda library in my solution:-
Check whether the key exist in any of the object in array by
idx = R.findIndex(R.propEq('name', 'ben'), a). If idx<0 then we can directly push the object else go to the next step.
We have the index(idx), we just have to do a[idx].age="--".

Rename value if it is duplicate in json -

When there are multiple entries, I only want to append "_1","_2"....etc to json object, making sure no data is lost. If this is input:
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18}
{name: "b", age: 19}];
I want the output to be
names_array_new = [
{name: "a", age: 15},
{name: "a_1", age: 16},
{name: "a_2", age: 17},
{name: "b", age: 18}
{name: "b_1", age: 19}
];
I have searched for this but only found how to remove duplicates when entire objects are same or retain the last found value.
there are possibly better solutions, but i came up with such quick snippet. take it and make better.
name_changer = (n) => {
splitted = n.split("_");
if(splitted.length > 1) {
name = splitted[0];
ord = parseInt(splitted[1]);
return `${name}_${ord+1}`
} return `${n}_${1}`
}
stack = []
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18},
{name: "b", age: 19}
];
names_array.forEach(obj => {
if (stack.indexOf(obj.name) > -1) {
obj.name = name_changer(obj.name);
} stack.push(obj.name);
})
console.log(names_array);
You can use the function Array.prototype.reduce to generate the desired output.
The handler basically keeps the previous processed values in order to save the current count and finally we get the result from the accumulator.
let arr = [ {name: "a", age: 15}, {name: "a", age: 16}, {name: "a", age: 17}, {name: "b", age: 18}, {name: "b", age: 19}],
{result} = arr.reduce((a, {name: n, age}) => {
let key = a.counts[n] = (a.counts[n] || a.counts[n] === "" ? (+a.counts[n] + 1) : ""),
name = `${n}${key === "" ? "" : "_"}${key}`;
a.result.push({name, age});
return a;
}, {counts: {}, result: []});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can simply check the index and name of each a and b and then rename the value of that object keys with count++ with increment of count on each loop.
Just FYI - This can be improved more so wait for other solutions to come as well and choose what suits you best but this is simple and straight to your desired output!
Expected Output Demo:
var names_array = [{
name: "a",
age: 15
},
{
name: "a",
age: 16
},
{
name: "a",
age: 17
},
{
name: "b",
age: 18
}, {
name: "b",
age: 19
}
];
var countA = 1 //count increase for a
var countB = 1 //count increase for b
names_array.forEach(function(obj, index) {
if (obj.name == 'a' && index >= 1) {
obj.name = obj.name + '_' + countA++; //rename a
}
if (obj.name == 'b' && index >= 4) {
obj.name = obj.name + '_' + countB++; //rename b
}
});
console.log(names_array)
You could use a lookup object with key-value pairs of name value and its occurence
const nameValueLookup = {}
const namesArray = [
{ name: "a", age: 15 },
{ name: "a", age: 16 },
{ name: "a", age: 17 },
{ name: "b", age: 18 },
{ name: "b", age: 19 },
]
const res = namesArray.map((obj) => {
if (nameValueLookup[obj.name]) {
return { ...obj, name: `${obj.name}_${nameValueLookup[obj.name]++}` }
} else {
nameValueLookup[obj.name] = 1
return obj
}
})
console.log(res)

return the length of an array with the condition in it

function(people){
}
people([{name: 'John', age: 22},{name: 'paul', age: 23},{name: 'mathew', age: 24},])
How to return the length of an array consisting of person age more than 22 years old which should be 2.
You can use array reduce to count:
function people(array){
return array.reduce((total, current)=>{
if(current.age>22)
total = total +1;
return total;
},0);
}
console.log(people([{name: 'John', age: 22},{name: 'paul', age: 23},{name: 'mathew', age: 24},]));
Below is the functional programming approach to your question:
const persons = [
{name: 'John', age: 22},
{name: 'paul', age: 23},
{name: 'mathew', age: 24}
]
const over22 = persons.filter(person => person.age > 22)
console.log('there are', over22.length, 'people aged over 22')
Hope this helps.
Cheers,
Please try following :
function find_length(checkField, valueField, myArray) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][checkField] == valueField) {
return Object.keys(myArray[i]).length;
}
}
}
var myList = [{name: 'John', age: 22}, {name: 'paul', age: 23}, {name: 'mathew', age: 24},];
var ageObjLength = find_length('age', '22', myList );
alert("Length is " + ageObjLength);

Remove array duplicates by property javascript

I have a list of objects:
[{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
I need a simple way to filter out duplicates with regard to the name property, so:
[{name: "bob", age: "14"}, {name: "sue", age: "21"}]
There seem to be quite a few array duplicate removal questions, but not any based on a property. It can ignore all other fields.
Iterate the array, place all name values in a hash and skip objects whose name is already in the hash:
filterBy = function(ary, prop) {
var seen = {};
return ary.filter(function(item) {
var key = item[prop];
if(seen[key] === 1)
return false;
seen[key] = 1;
return true;
});
}
//
a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
b = filterBy(a, 'name');
console.log(b);
ES6 version:
filterBy = function(ary, prop) {
var seen = new Set();
return ary.filter(item => !seen.has(item[prop]) && seen.add(item[prop]));
}
a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
b = filterBy(a, 'name');
console.log(b);
You can do it with 2 for loops as follows. All you have to do is, keeping a result array and every time you insert into it, check whether the name attributes are equal.
function findDuplicate(){
var array= [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];
var result=[];
for(x in array){
var found=false;
for(y in result){
if(result[y].name.localeCompare(array[x].name)==0){
found=true;
}
}
if(!found){
result.push(array[x]);
}
}
console.log(result);
}
You could do this with forEach and thisArg param.
var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];
var result = [];
data.forEach(function(e) {
if (!this[e.name]) {
this[e.name] = e;
result.push(this[e.name]);
}
}, {});
console.log(result)
Or with forEach and map()
var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}], result =[];
data.forEach(function(e) {
if(result.map(a => {return a.name}).indexOf(e.name) == -1 ) result.push(e);
});
console.log(result)
You could use Array#filter and a this object for marking, if the same name is already filtered.
var array = [{ name: "bob", age: "14" }, { name: "bob", age: "16" }, { name: "sue", age: "21" }],
filtered = array.filter(function (a) {
if (!this[a.name]) {
this[a.name] = true;
return true;
}
}, Object.create(null));
console.log(filtered);
For the straightforward comparison in the Q., there are some
good answers here. If you want to provide a custom comparison
function that will work on e.g. object values, or that uses
a RegExp, then take a look at the following.
var dedupwhen = function(fn, list){
if(list[0] === undefined){
return [];
}
// Join the first item to the remainder that has had the first
// item filtered out (according to fn) and then been
// deduplicated itself.
return [list[0]].concat(dedupwhen(fn, list.slice(1).filter(function(item){
return !fn(list[0], item);
})));
};
var similarname = function(x,y){
return RegExp('^' + x.name + '$', 'i').test(y.name);
};
var list = [
{name: 'Sue', age: 44},
{name: 'Bob', age: "14"},
{name: 'bob', age: "16"},
{name: 'sue', age: "21"}
];
console.log(dedupwhen(similarname, list));

Categories