I have this initial array:
const initialData = [
{
day: 1,
values: [
{
name: 'Roger',
score: 90,
},
{
name: 'Kevin',
score: 88,
},
{
name: 'Steve',
score: 80,
},
],
},
{
day: 2,
values: [
{
name: 'Roger',
score: 70,
},
{
name: 'Michael',
score: 88,
},
],
},
{
day: 3,
values: [
{
name: 'Steve',
score: 97,
},
],
},
];
to be converted into:
const result = [
{
name: 'Roger',
scores: [90, 70, null],
},
{
name: 'Kevin',
scores: [88, null, null],
},
{
name: 'Steve',
scores: [80, null, 97],
},
{
name: 'Michael',
scores: [null, 88, null],
},
];
I'm trying to use array map and create temporary array:
const holder = [];
initialData.map()
but to no avail
You can do this in a couple of steps - first reduce so you can index by name, and then map those entries to the format you expected
const initialData = [{day:1,values:[{name:"Roger",score:90},{name:"Kevin",score:88},{name:"Steve",score:80}]},{day:2,values:[{name:"Roger",score:70},{name:"Michael",score:88}]},{day:3,values:[{name:"Steve",score:97}]}];
var result = Object.entries(initialData.reduce( (acc,item) => {
item.values.forEach( v => {
if(!acc[v.name]) acc[v.name] = {};
acc[v.name][item.day] = v.score;
});
return acc;
},{})).map( ([name,days]) => ({
name,
scores: new Array(initialData.length).fill(null).map( (_,i) => days[i+1] || null)
}))
console.log(result);
You could use reduce and forEach to create one object for each name and then to get an array from that object you can just use Object.values method.
const data = [{"day":1,"values":[{"name":"Roger","score":90},{"name":"Kevin","score":88},{"name":"Steve","score":80}]},{"day":2,"values":[{"name":"Roger","score":70},{"name":"Michael","score":88}]},{"day":3,"values":[{"name":"Steve","score":97}]}]
const obj = data.reduce((r, { values }, i) => {
values.forEach(({ name, score }) => {
if (!r[name]) r[name] = { name, scores: Array(data.length).fill(null)}
r[name].scores[i] = score
})
return r;
}, {})
const result = Object.values(obj)
console.log(result)
Related
I want to copy value of name and age into another array, below code is working fine, But I wanted to know better way to do it.
const users = [
{ id: 0, name: 'John', age:34 },
{ id: 1, name: 'Wayne', age:44 },
{ id: 2, name: 'David', age:24 },
];
let values=[];
users && users.map(user => {
values.push(user['name'])
values.push(user['age'])
})
console.log(values);
output
['John', 34, 'Wayne', 44, 'David', 24]
You can bind each items to an array containing both its name and age and then flattern these arrays.
This can be done using Array#FlatMap
const users = [
{ id: 0, name: 'John', age:34 },
{ id: 1, name: 'Wayne', age:44 },
{ id: 2, name: 'David', age:24 },
];
const nameAndAges = users.flatMap(user => [user.name, user.age])
console.log(nameAndAges)
Your solution looks good, this can be also solved in different ways, I guess you may want to create function for handling this.
const users = [
{ id: 0, name: 'John', age: 34 },
{ id: 1, name: 'Wayne', age: 44 },
{ id: 2, name: 'David', age: 24 },
];
const result = mapArrayToProps(users, ['name', 'age']);
function mapArrayToProps(arr, props) {
return arr.flatMap(obj => mapObjectToProps(obj, props));
}
function mapObjectToProps(obj, props) {
return props.map(prop => obj[prop])
}
console.log(result);
I see that all the loops for objects returns the key as string and the value, but I want to operate on the keys of the object itself. If I have this object:
const data = {
person1: [
{ id: 1, name: Mike, age: 24 },
{ id: 2, name: Bob, age: 31 }
],
person2: [
{ id: 3, name: Christin, age: 21 },
{ id: 4, name: Michelle, age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
const persons = Object.keys(data).map(person => ...)
}
I wanted to loop through data and run .includes on each person in order to remove them by the id, but I am at a loss on how to do that.
You can loop through all keys and delete that the person you want by id using the filter() method
const removePersonById = (id) => {
var all = Object.keys(data);
for(let person of all){
data[person] = data[person].filter(a => a.id!=id);
}
}
You could get the values and find the index. Then splice.
const
removePersonById = id => {
Object.values(data).forEach(a => {
const index = a.findIndex(o => o.id === id);
if (index !== 0) a.splice(index, 1);
});
};
You could use .some()
const data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
Object.keys(data).map(person => {
if (data[person].some(p => p.id === id)) delete data[person];
})
}
removePersonById(3)
console.log(data)
Use Object.entries() so you can iterate over the keys and values together. Then you can test the value to see if the id is found.
Then use the delete operator to remove that key from the object.
const removePersonById = id => {
delete data[id];
};
const data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
};
const removePersonById = (id) =>
Object.entries(data).forEach(([key, value]) => {
if (value.some(({id: personid}) => personid == id)) {
delete data[key];
}
});
removePersonById(3);
console.log(data);
let data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
data = Object.keys(data).reduce((acc,key) => {
if(data[key].some(person=>person.id===id)) return acc
acc[key]= data[key]
return acc
}, {})
console.log(`Remove person with ID ${id}: `,data)
}
removePersonById(1)
Suppose I got an object defined as such:
const me = {
id: 1,
name: 'James',
age: 40,
family: {
mother: {
id: 101,
name: 'Bea',
age: 66
},
father: {
id: 102,
name: 'Martin',
age: 69
},
children: [
{
id: 11,
name: 'Tom',
age: 18,
},
{
id: 12,
name: 'Nancy',
age: 13,
},
],
},
}
How does one easily access a value by just giving an array of strings of the chained properties' names?
For example, calling:
search(me, ['family', 'father', 'age'])
which would be the same as:
me['family']['father']['age']
would return 69.
PS:
What about having search(me, ['family', 'children', 'name']) return ['Tom', 'Nancy']?
PSS:
Or even search(me, ['family', 'children', ['name', 'age']]) returning
[
{
name: 'Tom',
age: 18
},
{
name: 'Nancy',
age: 13
}
]
EDIT:
I went checking out lodash/deepdash libraries, but couldn't really figure it out by myself.
You can do that with this simple recursive function which takes an array as the query:
const me = {
id: 1,
name: 'James',
age: 40,
family: {
mother: {
id: 101,
name: 'Bea',
age: 66
},
father: {
id: 102,
name: 'Martin',
age: 69
},
children: [
{
id: 11,
name: 'Tom',
age: 18,
},
{
id: 12,
name: 'Nancy',
age: 13,
},
],
},
}
function search(obj, [first, ...rest]) {
return rest.length ? search(obj[first], rest) : obj[first];
}
const result = search(me, ['family', 'father', 'age']);
console.log(result);
Though it's bit lengthy, you could try this for all your combinations.
const me={id:1,name:'James',age:40,family:{mother:{id:101,name:'Bea',age:66},father:{id:102,name:'Martin',age:69},children:[{id:11,name:'Tom',age:18,},{id:12,name:'Nancy',age:13,},],},}
function search(data, searchPattern) {
const keys = [...searchPattern];
//picking last key and it's corresponding value
const lastKey = keys.pop();
const resultInst = keys.reduce((acc,key)=>{
return acc[key];
}, data);
// if it's array iterating it further to construct the response
if (Array.isArray(resultInst)) {
return resultInst.map(inst => {
if (Array.isArray(lastKey)) {
return lastKey.reduce((accInner,key) => {
accInner[key] = inst[key];
return accInner;
}, {});
} else {
return inst[lastKey];
}
});
} else {
// else just returning property's value
return resultInst[lastKey];
}
}
console.log(search(me, ['family', 'father', 'age']))
console.log(search(me, ['family', 'children', 'name']))
console.log(search(me, ['family', 'children', ['name', 'age']]))
Some interesting requirements you have there! Here is an all-in-one answer using object-scan and lodash
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/lodash#4.17.21"></script>
<script type="module">
import objectScan from 'https://cdn.jsdelivr.net/npm/object-scan#18.1.2/lib/index.min.js';
const myData = { id: 1, name: 'James', age: 40, family: { mother: { id: 101, name: 'Bea', age: 66 }, father: { id: 102, name: 'Martin', age: 69 }, children: [{ id: 11, name: 'Tom', age: 18 }, { id: 12, name: 'Nancy', age: 13 }] } };
const search = (data, needle) => objectScan([needle], {
reverse: false,
rtn: ['key', 'value'],
useArraySelector: false,
afterFn: (state) => {
if (state.result.length === 0) {
state.result = undefined;
} else if (needle.includes('{')) {
const prefixLength = lodash
.zip(...state.result.map(([k]) => k))
.findIndex((e) => new Set(e).size > 1);
const result = [];
state.result.forEach(([k, v]) => lodash.set(result, k.slice(prefixLength), v));
state.result = result;
} else if (
state.result.length === 1
&& state.result.every(([k]) => k.every((p) => typeof p === 'string'))
) {
state.result = state.result[0][1];
} else {
state.result = state.result.map(([k, v]) => v);
}
}
})(data);
console.log(search(myData, 'family.father.age'));
// => 69
console.log(search(myData, 'family.children.name'));
// => [ 'Tom', 'Nancy' ]
console.log(search(myData, 'family.children.{age,name}'));
// => [ { name: 'Tom', age: 18 }, { name: 'Nancy', age: 13 } ]
console.log(search(myData, 'family.father.unknown'));
// => undefined
</script>
Disclaimer: I'm the author of object-scan
const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
output: user 10,12 and 15 liked on your story ID 25
I want to show output like above. How to merge and show those like the output. Any idea?
You need to create a hash map, check the code snippet below:
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = {};
for (let data of allData) {
if (data.story in hash) hash[data.story] = [...hash[data.story], { ...data }];
else hash[data.story] = [{ ...data }];
}
console.log(hash);
You should use Map, which is what I would suggest. The code below does the same thing but using Maps.
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = new Map();
for(let data of allData) {
const currentVal = hash.get(data.story);
if (currentVal) hash.set(data.story, [...currentVal, {...data}])
else hash.set(data.story, [{...data}])
}
console.log(hash);
I cann't comment. So i write here!
Are you wanting ...
result = [
{
story_id : 25,
user_id : [10, 12, 15]
}
]
Right?
This is solution of me
const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
var result = data.reduce((res, item) => {
let storyID = item.story_id;
if (typeof res[storyID] == 'undefined') {
res[storyID] = {
story_id: storyID,
user_id: []
}
}
res[storyID].user_id.push(item.user_id);
return res;
}, []);
result = Object.values(result);
let selected = [
{id: 15, name: 'Canada'},
{id: 25, name: 'Germany'}
];
let all = [
{id: 15, name: 'Canada'},
{id: 25, name: 'Germany'},
{id: 32, name: 'United States'},
{id: 40, name: 'China'}
]
How do I get non-selected countries from all objects and print it out in another variable? Based on id key of those which are in selected array?
You need to find all objects that aren't contained in selected and then do something with them:
let nonSelectedItems = all.filter(obj => selected.every(s => s.id !== obj.id));
//do stuff with non-selected items
You can use filter and find, so as soon as element with same id is found in selected it will filter out that element from all. You can also use some instead of find.
let selected = [
{id: 15, name: 'Canada'},
{id: 25, name: 'Germany'}
];
let all = [
{id: 15, name: 'Canada'},
{id: 25, name: 'Germany'},
{id: 32, name: 'United States'},
{id: 40, name: 'China'}
]
var r = all.filter(e => !selected.find(a => e.id === a.id));
console.log(r)
Generate an object which holds id as a property using Array#reduce method(which helps to speed up since you need to iterate over and over) and use Array#filter method to filter elements from all array.
// generate the object reference
let ref = selected.reduce(function(obj, o) {
// define property
obj[o.id] = true;
// return object property
return obj;
// set initial value as an object
}, {});
// filter out array elements
let res = all.filter(function(o) {
return !ref[o.id]
})
let selected = [{
id: 15,
name: 'Canada'
}, {
id: 25,
name: 'Germany'
}];
let all = [{
id: 15,
name: 'Canada'
}, {
id: 25,
name: 'Germany'
}, {
id: 32,
name: 'United States'
}, {
id: 40,
name: 'China'
}]
let ref = selected.reduce(function(obj, o) {
obj[o.id] = true;
return obj;
}, {});
console.log(
all.filter(function(o) {
return !ref[o.id]
})
)
With ES6 arrow function :
let ref = selected.reduce((obj, o) => (obj[o.id] = true, obj), {});
let res = all.filter(o => !ref[o.id]);
let selected = [{
id: 15,
name: 'Canada'
}, {
id: 25,
name: 'Germany'
}];
let all = [{
id: 15,
name: 'Canada'
}, {
id: 25,
name: 'Germany'
}, {
id: 32,
name: 'United States'
}, {
id: 40,
name: 'China'
}]
let ref = selected.reduce((obj, o) => (obj[o.id] = true, obj), {});
console.log(
all.filter(o => !ref[o.id])
)