How to add duplicate key elements in JavaScript Object? - javascript

I want to make the following newArray using by following testArray.
newArray↓
let newArray = [
{section:"business",name:["Bob","John"]},
{section:"H&R",name:["Jen","Bobby"]},
]
testArray↓
let test = [
{section:"business",name:"Bob"},
{section:"business",name:"John"},
{section:"H&R",name:"Jen"},
{section:"H&R",name:"Bobby"},
]
First of all, I tried to find some key elements using by filter method like below.
let newArray = test.filter((x:any,i,self)=>
self.indexOf(x.section)===i
)
but this code output is [].
So, how do I make code to get my expected output?
Does anyone help me?

Use Array.reduce():
let test=[{section:"business",name:"Bob"},{section:"business",name:"John"},{section:"H&R",name:"Jen"},{section:"H&R",name:"Bobby"}];
let newArray = test.reduce((acc,cur) => {
if(acc.some(el => el.section === cur.section)){
acc.forEach((el,idx) => {
if(el.section === cur.section){
acc[idx].name.push(cur.name)
}
})
}else{
cur.name = [cur.name]
acc.push(cur)
}
return acc
},[])
console.log(newArray)

you can try this
const test = [{
section: "business",
name: "Bob"
},
{
section: "business",
name: "John"
},
{
section: "H&R",
name: "Jen"
},
{
section: "H&R",
name: "Bobby"
},
];
// gather sections
const sections = {};
test.forEach(t => {
sections[t.section] = sections[t.section] || [];
sections[t.section].push(t.name);
});
// convert sessions to array
const newArray = Object.keys(sections).map(k => {
return {
section: k,
name: sections[k]
};
});
console.log(newArray);

Related

Check if an object in an array is exist in another array, then change the value of that another array in Javascript

i have an array A
const arrayA = [
{
id:a,
check:false
},
{
id:b,
check:false
},
{
id:c,
check:false
}
and an array B
const arrayB = [
{
id:a,
},
{
id:b,
}
]
and i want to check if arrayB is exist arrayA by id, then change check to true. Using lodash or js array methods
Hopefully I understood your question correctly but this is the solution I came up with.
arrayA.map((item) => ({ ...item, check: arrayB.some(({ id: idB }) => item.id === idB ) }))
You can use nested forEach loops, and check, if id matches then set check to true.
const arrayA = [{
id: "a",
check: false
},
{
id: "b",
check: false
},
{
id: "c",
check: false
}
]
const arrayB = [{
id: "a",
},
{
id: "b",
}
]
arrayB.forEach((b)=>{
arrayA.forEach((a)=>{
if(b.id == a.id){
a.check = true;
}
})
})
console.log(arrayA);
You could create an array containing the ids of arrayB and then check the objects in arrayA like
const arrayA = [
{
id: 'a',
check:false
},
{
id:'b',
check:false
},
{
id:'c',
check:false
} ];
const arrayB = [
{
id:'a',
},
{
id:'b',
}
];
const idsB = arrayB.map( obj => obj.id);
arrayA.forEach(obj => { if(idsB.indexOf(obj.id) > -1) obj.checked = true; } );
arrayA.forEach(obj => {console.log(JSON.stringify(obj))});
I could come up with this, which is not different than double loop, but may read easier.
arrayA.map((a) => {
a.check = arrayB.findIndex((b) => b.id === a.id) != -1;
return a;
});
Try this code it may help you
const arrayA = [
{id:'a',check:false},
{id:'b',check:false},
{id:'c',check:false}
]
const arrayB = [
{id:'a',},
{id:'b',}
]
arrayB.map(i => {
return i.check = arrayA.find(item => i.id == item.id)?.check;
});
console.log(arrayB)

Joining two arrays of JSON objects like an SQL join using functional programming

Consider, I have the following two arrays of objects:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
What I want to do is determine which of the bookings in the second array are new and which are existing. Any bookingId that is in both arrays is existing. Any bookingID that is in the second array but not the first is new. So, the result of the solution should be an array as follows:
[ { bookingId: -2, existing: true, name: 'name1' },
{ bookingId: -3, existing: false, name: 'name1' },
{ bookingId: -1, existing: true, name: 'namex' } ]
I have a solution (which I'll post as an answer), but I think there's probably a more efficient way of doing it. Good luck.
If you want a non-R answer: you can use a simple map to iterate over the data, compare the booking ids in both arrays (with some), and return a new array of objects.
const existingAndArchivedBookings = [{booking_id:-2},{booking_id:-1},{booking_id:999}];
const newAndExistingBookings = [{bookingId:-2, name: "name1"},{bookingId:-3, name: "name1"},{bookingId:-1, name: "namex"}];
function testBookings(arr1, arr2) {
return arr2.map(({ bookingId, name }) => {
const existing = arr1.some(obj => obj.booking_id === bookingId);
return { bookingId, existing, name };
});
}
const out = testBookings(existingAndArchivedBookings, newAndExistingBookings);
console.log(out);
You can greatly simplify it using Array.prototype.reduce to form the result of the comparisons between the 2 arrays and Array.prototype.findIndex to test whether the object in the second array is present in the first array:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
const res = newAndExistingBookings.reduce((acc, ele) => {
const idx = existingAndArchivedBookings.findIndex(b => b.booking_id === ele.bookingId);
let existing = false;
if(idx >=0 ){
existing = true;
}
return acc.concat({bookingId : `${ele.bookingId}`, existing: `${existing}`, name: `${ele.name}`});
}, []);
console.log(res);
Here's what I came up with, which seems a bit long winded
const R = require('ramda')
const existingAndArchivedBookings = [{"booking_id":-2},{"booking_id":-1},{"booking_id":999}]
const newAndExistingBookings = [{bookingId:-2, name: "name1"}, {bookingId:-3, name: "name1"}, {bookingId:-1, name: "namex"}]
const existingAndArchivedKeys = existingAndArchivedBookings.map(value => value.booking_id)
const newAndExistingKeys = newAndExistingBookings.map(value => value.bookingId)
const existingKeys = existingAndArchivedKeys.filter(key => newAndExistingKeys.includes(key))
const newKeys = newAndExistingKeys.filter(key => !existingAndArchivedKeys.includes(key))
const existingBookingIds = existingKeys.map(key => {
return {bookingId: key, existing: true}
})
const newBookingIds = newKeys.map(key => {
return {bookingId: key, existing: false}
})
const allArray = R.concat(newAndExistingBookings, R.concat(existingBookingIds, newBookingIds))
console.log(R.values(R.reduceBy(R.mergeLeft, {}, R.prop('bookingId'), allArray)))

lodash filter not finding value in multidimensional array of Shopify order

Looking to see if an order line_item has been refunded before processing...
Here is a single order:
var order = {
line_items: [
{
id: 1326167752753
}
],
refunds: [
{
refund_line_items: [
{
id: 41264152625,
line_item_id: 1326167752753,
}
]
}
]
};
Trying to log out the filter results:
console.log(
_.filter(order, {
refunds: [
{
refund_line_items: [
{
line_item_id: 1326167752753
}
]
}
]
}).length
);
I'm getting 0 on the console.
Am I using _.filter wrong in this case?
Function take needs an array (order is not an array, order.refunds is) and a predicate, not an object.
Anyway, I'd write it using Array.some:
const itemWasRefunded = order.refunds.some(refund =>
refund.refund_line_items.some(refund_line_item =>
refund_line_item.line_item_id === 1326167752753
)
);
Or, alternatively, getting all line_item_ids and checking inclusion:
const itemWasRefunded = _(order.refunds)
.flatMap("refund_line_items")
.map("line_item_id")
.includes(1326167752753);
You can use some and find and do this in lodash and also easily in ES6:
var order = { line_items: [{ id: 1326167752753 }], refunds: [{ refund_line_items: [{ id: 41264152625, line_item_id: 1326167752753, }] }] };
// lodash
const _searchRefunds = (lid) => _.some(order.refunds, x =>
_.find(x.refund_line_items, {line_item_id: lid}))
console.log('loadsh:', _searchRefunds(1326167752753)) // true
console.log('loadsh:', _searchRefunds(132616772323232352753)) // false
//es6
const searchRefunds = (lid) => order.refunds.some(x =>
x.refund_line_items.find(y => y.line_item_id == lid))
console.log('ES6:', searchRefunds(1326167752753)) // true
console.log('ES6:', searchRefunds(132616772323232352753)) // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Filter array items using forEach

I have one question about filter array in forEach. So I would like filter (bigger than in example) array using outside variable filterKey. I think that my function is correct by after filtered newArr is undefined. Could you explain what is incorrect?
var filterKey = 123456,
var array = [{
ratings:{ users:[id: 123456]}, user: xyz
},
{
ratings:{users:[id:9787389023]}, user:zyx
}],
And my filter function
var newArr = array.forEach((ele) =>
ele.ratings.users.filter((newEl) =>
newEl.id == filterKey))
Use array.filter method
let array = [
{
id: 123456, user: 'xyz'
},
{
id:9787389023, user: 'zyx'
},
{
id: 123456, user: 'che'
}
]
let newArray = array.filter((element) => element.id === 123456)
console.log(newArray)
Use .filter and you'll be able to filter your result set without using foreach since it'll loop across the array.
var find = 123456;
var arr = [
{
id: 123456,
user: 'john'
},
{
id: 9787389023,
user: 'leah'
}
];
var results = arr.filter(function(node) {
return node.id === find;
});
console.log(results);

Remove parent object and child object if value is undefined using Array.filter(?)

Question:
How can I removal all emailAddress that are empty, and if there are no emailAddresses for an approval, remove that approval too.
My current solution will remove approvals when emailAddress completely empty. But not when two emailAddresses are present and one is empty (see script output vs. expected output)
var request = {
approvals: [
{
type: 'media',
emailAddresses: [
{emailAddress: 'frank#gmail.com'},
]
},
{
type: 'other',
emailAddresses: [
{emailAddress: ''},
]
},
{
type: 'scope',
emailAddresses: [
{emailAddress: 'kelly#yahoo.com'},
{emailAddress: ''},
]
}
]
}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
let output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
// EXPECTED OUTPUT:
// approval: [
// {
// type: 'media',
// emailAddresses: [
// {emailAddress: 'frank#gmail.com'},
// ]
// },
// {
// type: 'scope',
// emailAddresses: [
// {emailAddress: 'kelly#yahoo.com'},
// ]
// }
// ]
// }]
Live Code
You are not replacing approval.emailAddresses in your code - you should use:
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
See demo below:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var filterOutEmptyEmails = (approval) => {
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
if(approval.emailAddresses.length){
return true;
}
}
var output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
EDIT:
Another proposal without mutating the input array - using Array.prototype.reduce to create a new array:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var output = request.approvals.reduce(function(p,c){
// creates a shallow copy
var elem = Object.assign({},c);
// replaces the reference to request.approvals by the new array created by the filter
elem.emailAddresses = elem.emailAddresses.filter(x => !!x.emailAddress);
if(elem.emailAddresses.length != 0)
p.push(elem);
return p;
},[]);
// console.log(request.approvals);
console.log(output);
.as-console-wrapper{top:0;max-height:100%!important;}
Possible "non mutation" solution could be like this
var request = {approvals: [{type: 'media',emailAddresses: [{emailAddress: 'frank#gmail.com'},]},{type: 'other',emailAddresses: [{emailAddress: ''},]},{type: 'scope', emailAddresses: [{emailAddress: 'kelly#yahoo.com'},{emailAddress: ''},]}]}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
const output = request.approvals.map(approval => {
const filteredAproval = approval;
filteredAproval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
return filteredAproval
}).filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
console.log(JSON.stringify(request));
Without mutation (with lots of ES6/7 sugar):
const filteredApprovals = request.approvals.reduce((acc, approval) => {
const filteredEmailAddresses = approval.emailAddresses.filter(item => item.emailAddress);
return (filteredEmailAddresses.length > 0) ? [...acc, { ...approval, emailAddresses: filteredEmailAddresses }] : acc;
}, []);
Fiddle: https://jsfiddle.net/free_soul/hndjbce3/

Categories

Resources