Delete multiple items in one array in react state from another array - javascript

I have this array
let deleted = [
{id: '123', name: 'Something'},
{id: '321', name: 'Something1'}
];
and I have this
this.setState({
config: {
...this.state.config,
categories: this.state.config.categories.map(cat => ({
...cat,
movies: [...cat.movies, ...currentMovies]
}))
}
});
Every movies array for every category contains all items from deleted array but are not the same arrays because some contains selected property and some not, but movie id's are the same.
How can I delete every item from delete array from every categories.movies array?
I am thinking to iterate through deleted and then for every item in that array do
movies: this.state.config.categories.filter(item => item.id !== deleted.id)
But i do not know if that's a best solution, can someone help?
Thanks in advance

This should work. filter the movies as well with map.
const filt = (item) => item.id !== deleted.id;
this.state.config.categories.filter(filt).map(({ movies, ...rest }) => ({
...rest,
movies: movies.filter(filt),
}));

It isn't very clear what the state structure is, but to filter the movies array by checking against an array of movies to delete can be done a couple ways using an array::filter function.
Search the deleted array each iteration and check if the movie id's match (O(n) linear search). If no match found then include in the result.
movies.filter(movie => !deleted.some(({ id }) => movie.id === id))
let deleted = [
{ id: "123", name: "Something" },
{ id: "321", name: "Something1" }
];
const currentState = {
movies: [
{ id: "120", name: "Something 120" },
{ id: "121", name: "Something 121" },
{ id: "122", name: "Something 122" },
{ id: "123", name: "Something" },
{ id: "124", name: "Something 124" },
{ id: "125", name: "Something 125" },
{ id: "321", name: "Something1" }
]
};
const nextState = currentState.movies.filter(
movie => !deleted.some(({ id }) => movie.id === id)
);
console.log(nextState)
Create a map of deleted movie ids so you don't have to search each time (O(1) constant-time search).
const deletedMovieIdSet = deleted.reduce((ids, { id }) => {
ids.add(id);
return ids;
}, new Set());
...
movies.filter(movie => !deletedMovieIdSet.has(movie.id))
let deleted = [
{ id: "123", name: "Something" },
{ id: "321", name: "Something1" }
];
const deletedMovieIdSet = deleted.reduce((ids, { id }) => {
ids.add(id);
return ids;
}, new Set());
const currentState = {
movies: [
{ id: "120", name: "Something 120" },
{ id: "121", name: "Something 121" },
{ id: "122", name: "Something 122" },
{ id: "123", name: "Something" },
{ id: "124", name: "Something 124" },
{ id: "125", name: "Something 125" },
{ id: "321", name: "Something1" }
]
};
const nextState = currentState.movies.filter(
movie => !deletedMovieIdSet.has(movie.id)
);
console.log(nextState)

Related

create new array from nested array object

i want to create a new array from api, but i don't know how to make it, i'm very confused in looping each array
This is each data
const group_one = [
{
name: "smash",
id: "012112"
},
{
name: "ahlan wa sahlan",
id: "123123"
},
{
name: "ahh",
id: "1231239"
},
{
name: "laki",
id: "21312"
}
];
const group_two = [
{
name: "ahh",
id: "1231239"
},
{
name: "laki",
id: "21312"
}
];
const group_three = [
{
name: "smash",
id: "012112"
},
{
name: "ahlan wa sahlan",
id: "123123"
}
];
this is the main data of api
const data = [
{
body: group_one,
group_id: "01"
},
{
body: grouop_two,
group_id: "02"
},
{
body: group_three,
group_id: "03"
}
];
export default data;
i want to create a new array like this, bcs i want to create a new object containing the group_id of each same data in the array
const newArray = [
{
name: "smash",
id: "012112",
group_id: ["01","03"]
},
{
name: "ahlan wa sahlan",
id: "123123",
group_id: ["01","03"]
},
{
name: "ahh",
id: "1231239",
group_id: ["01","02"]
},
{
name: "laki",
id: "21312",
group_id: ["01","02"]
}
];
can someone help me? with articles or codes.
thanks for helping me (sry for my bad english)
Please see below commented code:
const group01 = [
{
name: 'smash',
id: '012112'
},
{
name: 'ahlan wa sahlan',
id: '123123'
},
{
name: 'ahh',
id: '1231239'
},
{
name: 'laki',
id: '21312'
}
];
const group02 = [
{
name: 'ahh',
id: '1231239'
},
{
name: 'laki',
id: '21312'
}
];
const group03 = [
{
name: 'smash',
id: '012112'
},
{
name: 'ahlan wa sahlan',
id: '123123'
}
];
const data = [
{
body: group01,
group_id: '01'
},
{
body: group02,
group_id: '02'
},
{
body: group03,
group_id: '03'
}
];
function regroup(input) {
// USE Map FOR EASIER ITEM HANDLING.
const output = new Map();
// LOOP MAIN DATA ARRAY.
input.forEach(({body, group_id}) => {
// LOOP EACH GROUP.
body.forEach(({name, id}) => {
// USE id TO GET AN ITEM FROM output OR CREATE A NEW ONE IF IT DOES NOT EXIST.
const item = output.get(id) || {name, id, group_id: []};
// PUSH CURRENT group_id TO THE RESPECTIVE ARRAY.
item.group_id.push(group_id);
// SAVE ITEM TO OUTPUT Map AGAIN.
output.set(id, item);
});
});
// RETURN OUTPUT.
return Array.from(output.values());
}
const new_data = regroup(data);
console.log(new_data);

push value duplicate into new array

I have array of object like this
const data = [
{
name: "John",
transaction: "10/10/2010",
item: "Bag"
},
{
name: "Steven",
transaction: "31/10/2020",
item: "Shoe"
},
{
name: "John",
transaction: "18/06/2019",
item: "Sock"
}
]
you can see that the name of object in that array has duplicate name but different transaction
and then I want the result like this :
const result = [
{
name: "John",
transactions: [
{
date: "10/10/2010",
item: "Bag"
},
{
date: "18/06/2019",
item: "Sock"
}
]
},
{
name: "Steven",
transactions: [
{
date: "31/10/2020",
item: "Shoe"
}
]
},
]
so the new array recored the new transactions of the same person
the code for this is:
const data = [
{
name: "John",
transaction: "10/10/2010",
item: "Bag"
},
{
name: "Steven",
transaction: "31/10/2020",
item: "Shoe"
},
{
name: "John",
transaction: "18/06/2019",
item: "Sock"
}
]
let Transactions = []
data.forEach(data => {
Transactions.some(t => {
if(t.name === data.name){
t.transactions.push({date:data.transaction,item:data.item})
return;
}
})
Transactions.push({
name:data.name,
transactions:[
{date:data.transaction,item:data.item}
]
})
console.log(Transactions);
})
array.some is better than forEach loop i think.so decided to stick with that.
Please try the following example
const data = [
{
name: "John",
transaction: "10/10/2010",
item: "Bag",
},
{
name: "Steven",
transaction: "31/10/2020",
item: "Shoe",
},
{
name: "John",
transaction: "18/06/2019",
item: "Sock",
},
];
const output = data.reduce((previousValue, { name, transaction, item }) => {
const index = previousValue.findIndex((entry) => entry.name === name);
if (index === -1) {
previousValue = [
...previousValue,
{
name: name,
transactions: [{ date: transaction, item }],
},
];
} else {
previousValue[index].transactions = previousValue[
index
].transactions.concat({
date: transaction,
item,
});
}
return previousValue;
}, []);
console.dir(output, { depth: null, color: true });
See
Array.prototype.reduce()
Array.prototype.concat()
Array.prototype.findIndex()
a simple reduce do that
const data =
[ { name: 'John', transaction: '10/10/2010', item: 'Bag' }
, { name: 'Steven', transaction: '31/10/2020', item: 'Shoe' }
, { name: 'John', transaction: '18/06/2019', item: 'Sock' }
]
const result = data.reduce((a,{name,transaction:date,item})=>
{
let x = a.find(e=>e.name===name)
if (!x)
{
let n = a.push({name, transactions:[]}) -1
x = a[n]
}
x.transactions.push({date,item})
return a
},[])
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
shorter version
const result = data.reduce((a,{name,transaction:date,item})=>
{
let x = a.find(e=>e.name===name) || (a[a.push({name, transactions:[]}) -1])
x.transactions.push({date,item})
return a
},[])
You could do that in a functional way to make it readable, below worked solution is using ramdajs
const data = [
{
name: 'John',
transaction: '10/10/2010',
item: 'Bag'
},
{
name: 'Steven',
transaction: '31/10/2020',
item: 'Shoe'
},
{
name: 'John',
transaction: '18/06/2019',
item: 'Sock'
}
]
const result = pipe(
groupBy(obj => obj.name),
mapObjIndexed((groupObjs, groupName) => ({
name: groupName,
transactions: map(
groupObj => ({
date: groupObj.transaction,
item: groupObj.item
}),
groupObjs
)
})),
values
)(data)
console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script>const { groupBy, mapObjIndexed, pipe, map, values } = R</script>
Here is the link to the ramdajs doc
How about using lodash's _.groupBy() function?
const data = [
{
name: "John",
transaction: "10/10/2010",
item: "Bag",
},
{
name: "Steven",
transaction: "31/10/2020",
item: "Shoe",
},
{
name: "John",
transaction: "18/06/2019",
item: "Sock",
}
]
const result = _.groupBy(data, "name")
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>

Filter an object iside an array

I need to delete entire object that do not have passed
here is the array
const array = [{
course: 1,
list: [{
id: 1,
name: "john",
code: true
},
{
id: 1,
name: "maria",
code: true
},
]
},
{
course: 2,
list: [{
id: 3,
name: "rose"
},
{
id: 4,
name: "mark",
code: true
}
]
}
]
That i need is remove obj that not have code:true, and get this
const array = [{
course: 1,
list: [{
id: 1,
name: "john",
code: true
}, ]
},
{
course: 2,
list: [{
id: 1,
name: "mark",
code: true
}]
}
]
I tried to make a map inside a filter, but it does not work at all
const remove = array.filter(function(lines) {
return lines.map(line => line.list.map(list => list.code))
});
You can map through the array, then copy all properties of the specific item and separately do the filtering on the list attribute.
const array = [{
course: 1,
list: [{
id: 1,
name: "john",
code: true
},
{
id: 1,
name: "maria",
code: true
},
]
},
{
course: 2,
list: [{
id: 3,
name: "rose"
},
{
id: 4,
name: "mark",
code: true
}
]
}
]
const filter = arr => arr.map(arrItem => ({
...arrItem,
list: arrItem.list.filter( listItem => listItem.code )
})
)
console.log( filter(array) )
const filtered = [];
arr.forEach(item => {
const list = item.list.filter(listItem => listItem.code);
if(list.length > 0) {
filter.push({ ...item, list });
}
});
This approach will only add items to the filtered output array if the list contains any items after filtering out those with code: false. To include them anyway, you could do:
const filtered = arr.map(item => ({
...item,
list: item.list.filter(listItem => listItem.code)
});

React/Redux How to filter two array values

I am using react-reselect to filter out some data.
I have to different arrays of data which I have to check if they are matching or not. How can I do a filter with two different arrays and have to run map function on them
Here is my selector
export const AssignedUserSelector = createSelector(
[EmployeeSelector],
employee => {
const freshData = newData.map(newlyAssign => newlyAssign);
return employee.employees.filter(assign => assign.employeeId === newData);
}
);
here freshdata is something like this ["2222","333", "4444"] and employee.employees is like this [{id:"222", name: "John"}, {id:"333", name: "Jane"}, {id:"5555", name: "Josh"}].
What I am trying to do is filter out employees as per the id received. How I can I achieve this in react.
Not entirely sure what you're doing with your example code, but this is probably what you're looking for:
Multiple Ids
const employeeIds = ["2222", "333", "4444"];
const employee = {
employees: [{
id: "222",
name: "John"
},{
id: "333",
name: "Jane"
},{
id: "5555",
name: "Josh"
}]
};
employee.employees.filter(({ id }) => !employeeIds.includes(id));
Single Id
const employeeId = "222";
const employee = {
employees: [{
id: "222",
name: "John"
},{
id: "333",
name: "Jane"
},{
id: "5555",
name: "Josh"
}]
};
employee.employees.filter(({ id }) => id !== employeeId);

double nested array of object es6 filter

I want to filter out a nested array of objects but stuck at the filter part.
How to remove one of the mark?
this.state = {
data: [
{
id: 1,
name: "Main",
subs: [
{
id: "jay",
name: "Jay",
mark: [
{
id: "5a5d84b94a074c49ef2d4553",
name: 100
},
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}
]
}
]
};
https://codesandbox.io/s/p39momxzp7
I try to use es6 as it's more readable.
expected output
data: [
{
id: 1,
name: "Main",
subs: [
{
id: "jay",
name: "Jay",
mark: [
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}
]
}
]
Since there are multiple nested arrays in your data structure, you need to use forEach those many times
data.forEach( s => //iterate data
s.subs.forEach( t => //iterate subs
( t.mark = t.mark.slice( 1, 2 ) ) ) ); //slice the second value out
Demo
var data = [{
id: 1,
name: "Main",
subs: [{
id: "jay",
name: "Jay",
mark: [{
id: "5a5d84b94a074c49ef2d4553",
name: 100
},
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}]
}];
data.forEach(s => s.subs.forEach(t => (t.mark = t.mark.slice(1,2))));
console.log(JSON.stringify(data, 0, 4))
In case the last value should be picked?
data.forEach( s => //iterate data
s.subs.forEach( t => //iterate subs
( t.mark = t.mark.slice( -1 ) ) ) ); //slice the last value out
If you are trying to filter a relevant mark by a given id,
you can combine Array#map and Array#filter to achieve it:
Note that i'm also using the Object Rest/Spread Properties proposal (stage 4)
Running example
const state = {
data: [{
id: 1,
name: "Main",
subs: [{
id: "jay",
name: "Jay",
mark: [{
id: "5a5d84b94a074c49ef2d4553",
name: 100
}, {
id: "5a5d84b94a074119ef2d4553",
name: 70
}]
}]
}]
};
const mark_id = '5a5d84b94a074119ef2d4553';
const nextState = {
...state,
data: state.data.map(obj => {
const filteredSubs = obj.subs.map(sub => {
const markById = sub.mark.filter(m => m.id === mark_id);
return {
...sub,
mark: markById
}
});
return {
...obj,
subs: filteredSubs
}
})
};
console.log(nextState);
You can even use lodash which contains many methods that can be handled easily.
Check if this is what you are looking for. (there is a good scope to refactor it but before that would like to understand if thats what you are looking for)
Below is the code that has been used there.
let inputId = "5a5d84b94a074c49ef2d4553";
let filteredData =_.each(_.cloneDeep(data), function(value, key1) {
_.each(value.subs, function(valueSubs, key2) {
var finalSubMark = _.find(valueSubs.mark, function(eachMark) {
return eachMark.id == inputId;
});
_.set(valueSubs, "mark", finalSubMark);
});
});
https://codesandbox.io/s/v065w05rly

Categories