How to check if array of array contain atleast one element? - javascript

I am facing one problem in javascript filter.
Suppose this is an array1-
const array1 = [
{
title: 'Stock market news',
symbols: ['SPY.US', 'GSPC.INDX', 'DJI.INDX', 'CL.COMM', 'IXIC.INDX', 'NQ.COMM', 'ES.COMM'],
},
{
title: 'Neil Young urges Spotify',
symbols: ['SPOT.US', '639.F', '639.XETRA']
},
{
title: 'Neil Young urges Spotify',
symbols: ['AAPl.US', '639.F', '639.XETRA']
}
]
And this is an array2
const array2 = [
{Code: "AAPL"},
{Code: 'SPOT'}
]
I have to filer array1 and remove an object that not complete the condition. The condition is if the array1 symbols contain at least one element of array2 Code. I mean if the array2 Code is match arry1 symbols field at least one element.
In the above example, the result should be-
const array1 = [
{
title: 'Neil Young urges Spotify',
symbols: ['SPOT.US', '639.F', '639.XETRA']
},
{
title: 'Neil Young urges Spotify',
symbols: ['AAPl.US', '639.F', '639.XETRA']
}
]
Because this two object contain AAPL and SPOT in symbols field. I think I can clear all the things.
I am trying in this way-
const filterData = array1.filter(function (array1El) {
return !array2.find(function (array2El) {
return array1El.symbols.includes(`${array2El.Code}.US`);
})
});
But it is not working. Please say me where I am wrong.

There are two issues:
Your !array2.find condition is backwards - you want to filter to include items for which array2.find does have a match, not items for which it doesn't.
'AAPl.US' !== 'AAPL.US' - make them the same case before comparing.
It'd also be clearer to use .some instead of .find.
const array1 = [
{
title: 'Stock market news',
symbols: ['SPY.US', 'GSPC.INDX', 'DJI.INDX', 'CL.COMM', 'IXIC.INDX', 'NQ.COMM', 'ES.COMM'],
},
{
title: 'Neil Young urges Spotify',
symbols: ['SPOT.US', '639.F', '639.XETRA']
},
{
title: 'Neil Young urges Spotify',
symbols: ['AAPl.US', '639.F', '639.XETRA']
}
]
const array2 = [
{Code: "AAPL"},
{Code: 'SPOT'}
]
const filterData = array1.filter(function (array1El) {
return array2.some(function (array2El) {
return array1El.symbols
.map(s => s.toLowerCase())
.includes(`${array2El.Code.toLowerCase()}.us`);
})
});
console.log(filterData);
Or create a Set of matching symbols first, which I'd prefer for lower complexity.
const array1 = [
{
title: 'Stock market news',
symbols: ['SPY.US', 'GSPC.INDX', 'DJI.INDX', 'CL.COMM', 'IXIC.INDX', 'NQ.COMM', 'ES.COMM'],
},
{
title: 'Neil Young urges Spotify',
symbols: ['SPOT.US', '639.F', '639.XETRA']
},
{
title: 'Neil Young urges Spotify',
symbols: ['AAPl.US', '639.F', '639.XETRA']
}
]
const array2 = [
{Code: "AAPL"},
{Code: 'SPOT'}
];
const codesToFind = new Set(array2.map(({ Code }) => Code.toLowerCase() + '.us'));
const filterData = array1.filter(
({ symbols }) => symbols.some(
sym => codesToFind.has(sym.toLowerCase())
)
);
console.log(filterData);

We could use a regex alternation approach here:
const array1 = [
{
title: 'Stock market news',
symbols: ['SPY.US', 'GSPC.INDX', 'DJI.INDX', 'CL.COMM', 'IXIC.INDX', 'NQ.COMM', 'ES.COMM'],
},
{
title: 'Neil Young urges Spotify',
symbols: ['SPOT.US', '639.F', '639.XETRA']
},
{
title: 'Neil Young urges Spotify',
symbols: ['AAPL.US', '639.F', '639.XETRA']
}
];
const array2 = [{Code: "AAPL"}, {Code: "SPOT"}];
var regex = new RegExp("\\b(?:" + array2.reduce((x, y) => x.Code + "|" + y.Code) + ")\\.US");
console.log(regex); // /\b(?:AAPL|SPOT)\.US/
var output = array1.filter(x => x.symbols.some(e => regex.test(e)));
console.log(output);
The strategy here is to form a regex alternation of stock symbols, one of which is required. We then filter the original array, using some() and the regex to ensure that any match has at least one required stock symbol.

If you're doing this search multiple times, it would be best to build a symbol index and query that.
For example...
const array1 = [{"title":"Stock market news","symbols":["SPY.US","GSPC.INDX","DJI.INDX","CL.COMM","IXIC.INDX","NQ.COMM","ES.COMM"]},{"title":"Neil Young urges Spotify","symbols":["SPOT.US","639.F","639.XETRA"]},{"title":"Neil Young urges Spotify","symbols":["AAPl.US","639.F","639.XETRA"]}]
const array2 = [{Code: "AAPL"},{Code: 'SPOT'}]
// utility function to write into the index
const writeIndex = (map, key, entry) => {
const normalisedKey = String.prototype.toUpperCase.call(key)
if (!map.has(normalisedKey)) map.set(normalisedKey, new Set())
map.get(normalisedKey).add(entry)
}
const symbolIndex = array1.reduce((map, entry) => {
// convert all symbols to tokens
// eg AAPL.US becomes ["AAPL.US", "AAPL", "US"]
const keys = entry.symbols.flatMap(symbol =>
[symbol, ...symbol.split(".")])
// add the entry for each symbol token
keys.forEach(key => writeIndex(map, key, entry))
return map
}, new Map())
// pull unique items out of the index for the given codes
const queryIndex = codes => Array.from(new Set(codes.flatMap(code =>
[...symbolIndex.get(code) ?? []]
)))
console.log(queryIndex(array2.map(({ Code }) => Code)))
.as-console-wrapper { max-height: 100% !important; }
Alternatively, you can use a nested some clause with a string includes check to see if the symbol contains your code.
const array1 = [{"title":"Stock market news","symbols":["SPY.US","GSPC.INDX","DJI.INDX","CL.COMM","IXIC.INDX","NQ.COMM","ES.COMM"]},{"title":"Neil Young urges Spotify","symbols":["SPOT.US","639.F","639.XETRA"]},{"title":"Neil Young urges Spotify","symbols":["AAPl.US","639.F","639.XETRA"]}]
const array2 = [
{Code: "AAPL"},
{Code: 'SPOT'}
]
const normalise = str => str.toUpperCase()
const normalisedCodes = array2.map(({ Code }) => normalise(Code))
const filtered = array1.filter(({ symbols }) =>
normalisedCodes.some(code =>
symbols.some(symbol => normalise(symbol).includes(code))
)
)
console.log(filtered)
.as-console-wrapper { max-height: 100% !important; }

Related

Computing array of relationships from tags

I'm working on a d3-force visualisation, which requires
data in a specific shape. I've got an array of objects, each with an array of tags.
nodes = [
{ name: "post1", tag_list: ["activity", "online"] },
{ name: "post2", tag_list: ["workshop", "online"] },
{ name: "post3", tag_list: ["english", "workshop"] },
...
]
To establish connections between data, I need to explicitly define an array of links:
links = [
{
source: 'post1',
target: 'post2'
},
{
source: 'post2',
target: 'post3'
},
...
]
There is no difference in similarity between links - all relationships are linear and carry the same "agency". Identical data should ideally be filtered to prevent duplicate lines.
How can I generate a link array of the previously mentioned shape from the tag_list arrays?
Here's an example of the required data structure.
--
Some context: I'm trying to visualise thematic overlaps between blog pages. All pages have an array of tags to describe them (tag_list). I wish to connect all tags within the graph. Since d3 requires verbose references to draw links (see link below), I need to compute these from the tag lists that are accessible to me.
You could collect each tag, and for each tag collect the distinct names (in a Set). When such a tag already has names associated to it, iterate those and pair it with the "current" name, putting the lexically smaller name as first pair-member. Store this pair in a map of Sets, so that they are unique.
Here is an implementation:
let nodes = [
{ name: "post1", tag_list: ["activity", "online"] },
{ name: "post2", tag_list: ["workshop", "online"] },
{ name: "post3", tag_list: ["english", "workshop"] },
];
let tags = {};
let pairs = {};
let result = [];
for (let {name, tag_list} of nodes) {
for (let tag of tag_list) {
for (let other of tags[tag] ??= new Set) {
let [source, target] = [name, other].sort();
if (!(pairs[source] ??= new Set).has(target)) {
pairs[source].add(target);
result.push({source, target});
}
}
tags[tag].add(name);
}
}
console.log(result);
You can use hash grouping approach. First make an object where keys are hashes of the links, and then use only the values as the result.
const nodes = [
{ name: "post1", tag_list: ["activity", "online"] },
{ name: "post2", tag_list: ["workshop", "online"] },
{ name: "post3", tag_list: ["online"] },
{ name: "post4", tag_list: ["workshop"] },
{ name: "post5", tag_list: ["lonely"] },
];
const hasIntersection = (arrA, arrB) => arrA.some((el) => arrB.includes(el));
const groupedByHash = nodes.reduce((acc, targetNode) => {
const commonNodes = nodes
.filter(({ tag_list }) => hasIntersection(tag_list, targetNode.tag_list))
.filter(({ name }) => name !== targetNode.name);
if (commonNodes.length < 1) return acc;
const commonLinks = commonNodes.reduce((acc, { name }) => {
const [source, target] = [name, targetNode.name].sort();
const hash = [source, target].join('---');
acc[hash] = { source, target };
return acc;
}, {});
return { ...acc, ...commonLinks };
}, {});
const result = Object.values(groupedByHash);
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}

How to modify the groupBy result in Lodash

How to modify my script, so in result there is no key "author" (I want to have only song and place)?
The songs' list looks like that (obviously I do not copy whole list)
const lp3 = [
{
author: 'Queen',
song: 'Bohemian Rhapsody',
place: 1,
change: 0
},
{
author: 'Deep Purple',
song: 'Child in time',
place: 2,
change: 2
},
and my script:
const exercise10 = _.groupBy(lp3, "author")
and the result is e.g.:
Pink Floyd': [
{
author: 'Pink Floyd',
song: 'Shine on you crazy diamond',
place: 12,
change: 4
},
{
author: 'Pink Floyd',
song: 'Comfortably numb',
place: 15,
change: 7
},
{ author: 'Pink Floyd', song: 'Hey you', place: 18, change: 11 },
{
author: 'Pink Floyd',
song: 'Another brick in the wall part II',
place: 21,
change: 10
}
],
Using Array.reduce() or lodash's _.reduce() you can destructure each object, and take out author, and then group the objects:
const lp3 = [{"author":"Queen","song":"Bohemian Rhapsody","place":1,"change":0},{"author":"Deep Purple","song":"Child in time","place":2,"change":2}]
const result = _.reduce(lp3, (acc, { author, ...o }) => {
if(!acc[author]) acc[author] = []
acc[author].push(o)
return acc
}, {})
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
If you want to use _.groupBy() you'll need to group the items, and then map the groups with _.mapValues(), and map the items to omit author:
const lp3 = [{"author":"Queen","song":"Bohemian Rhapsody","place":1,"change":0},{"author":"Deep Purple","song":"Child in time","place":2,"change":2}]
const result1 = _.mapValues(
_.groupBy(lp3, 'author'),
values => _.map(values, o => _.omit(o, 'author')),
)
// or using chaining
const result2 = _(lp3)
.groupBy(lp3, 'author') // create the groups
.mapValues(values => // map the values of the groups x
_.map(values, o => _.omit(o, 'author')) // map the items
)
.value()
console.log(result1)
console.log(result2)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>

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)))

Mapping the array element with other array

I have two arrays
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
I have to map the id of the array1 to tags of the array2 and display the corresponding title from the array1.
The new array2 should look like,
array2=[{tags:"Writing",title:"USA", type:"text"},
{tags: "Writing,Singing,Dance",title: "Japan",type: "image"},
{tags: "Singing,Dance",title: "Japan",type: "image"}];
I did this to get the array1 mapping and got stuck after that.
var newtags= (array1).map(obj=>{
var rObj={};
rObj[obj.id]=obj.title;
return rObj;
});
You can create a mapping object with each id as key and title as value using reduce. Then map over array2 and split each tags to get the new tags
const array1=[{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}],
array2=[{tags:"1",title:"USA",type:"text"},{tags:"1,2,3",title:"Japan",type:"image"},{tags:"2,3",title:"Japan",type:"image"}]
const map = array1.reduce((r, { id, title }) => ({ ...r, [id]: title }), {});
const output = array2.map(({ tags, ...rest }) => {
const newTags = tags.split(',').map(id => map[id]).join(',')
return { tags: newTags, ...rest }
})
console.log(output)
You could also get the mapping object using Object.fromEntries()
const map = Object.fromEntries(array1.map(({ id, title }) => [id, title]));
Then use the regex /\d+(?=,|$)/ to match the numbers and replace them with their respective titles
const array1=[{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}],
array2=[{tags:"1",title:"USA",type:"text"},{tags:"1,2,3",title:"Japan",type:"image"},{tags:"2,3",title:"Japan",type:"image"}]
const map = Object.fromEntries(array1.map(({ id, title }) => [id, title]));
const output = array2.map(({ tags, ...rest }) => {
const newTags = tags.replace(/\d+(?=,|$)/g, n => map[n])
return { tags: newTags, ...rest }
})
console.log(output)
Here's a solution
I'm using .map, .reduce and .replace to join array1 and array2 together.
const array1 = [
{
id: "1",
title: "Writing"
},
{
id: "2",
title: "Singing"
},
{
id: "3",
title: "Dance"
}
]
const array2 = [
{
tags: "1",
title: "USA",
type: "text"
},
{
tags: "1,2,3",
title: "Japan",
type: "image"
},
{
tags: "2,3",
title: "Japan",
type: "image"
}
]
const array3 =
array2.map(item => ({
...item,
tags: array1.reduce((tags, {id, title}) => tags.replace(id, title), item.tags),
}))
console.log(array3)
You can use filter, map and join method, split tags and filter tags in array1 first.
var newtags= (array2).map(obj=>{
let tags = obj.tags.split(",");
let titles = array1.filter(c=>tags.includes(c.id)).map(c=>c.title);
obj.tags = titles.join();
return obj;
});
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
var newtags= (array2).map(obj=>{
let tags = obj.tags.split(",");
let titles = array1.filter(c=>tags.includes(c.id)).map(c=>c.title);
obj.tags = titles.join();
return obj;
});
console.log(newtags);
You can try following
Use Array.reduce to convert array1 into an object with id as key and title as value (Step 1)
Iterate over array2 using Array.forEach to update its tags property
To update tags property first split it by , to convert into an array
Map each value in array to its corresponding value in Object created in step 1
Join back the array with , and assign back to tags
let array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
let array2 = [{tags: "1",title: "USA",type: "text"},{tags: "1,2,3",title: "Japan",type: "image"},{tags: "2,3",title: "Japan",type: "image"}];
let obj = array1.reduce((a,c) => Object.assign(a, {[c.id] : c.title}), {});
array2.forEach(o => o.tags = o.tags.split(",").map(v => obj[v]).join(","));
console.log(array2);
To achieve expected result, use below option of looping array1 and replacing array2 tags with title
Loop Array1 using forEach
Replace array2 tags with each array1 title using array id
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
array1.forEach(v =>{
const re = new RegExp(v.id, "g");
array2 = JSON.parse(JSON.stringify(array2).replace(re, v.title))
})
console.log(array2);
I would consider breaking this down into several reusable functions. Of course it might be premature abstraction, but I've seen variants of this questions like often enough here that it makes sense to me to look toward the fundamentals.
We want to be able to look up the values in a list stored as an array with what might be arbitrary field names. So we use a function makeDictionary that takes both the field names and the array and returns an object that maps them, such as {'1': 'Writing', '2': 'Singing',...}`.
Then we can use fillField supplying a dictionary, a field name, and an object, and replace that field with the result of looking up the tags in the dictionary. This is a little more specific to the problem, mostly because the comma-separated string format for your tags is a little more cumbersome than it might be if it were an array.
With these, useTags is simple to write, and it is the first function here focused directly on your needs. It combines the above, supplying the field names id and title for the dictionary and tags for your main objects.
This is what it looks like combined:
const makeDictionary = (keyName, valName) => (arr) =>
arr .reduce
( (a, {[keyName]: k, [valName]: v}) => ({...a, [k]: v})
, {}
)
const fillField = (field, dict) => ({[field]: f, ...rest}) => ({
...rest,
[field]: f .split (/,\s*/) .map (t => dict[t]) .join (', ')
})
const useTags = (tags, dict = makeDictionary ('id', 'title') (tags) ) =>
(objs) => objs .map ( fillField ('tags', dict) )
const tags = [{id: "1", title: "Writing"}, {id: "2", title: "Singing"}, {id: "3", title: "Dance"}];
const updateTags = useTags (tags)
const items = [{tags: "1", title: "USA", type: "text"}, {tags: "1, 2, 3", title: "Japan", type: "image"}, {tags: "2, 3", title: "Japan", type: "image"}];
console .log (
updateTags (items)
)
Note that I took a little liberty with the tags: "2,3" and tags: "Singing,Dance" formats, adding a little white space. It's trivial to take this out. But even better, if possible, would be to change this to use arrays for your tags.
You could take a real Map and map the values to the new objects.
var array1 = [{ id: "1", title: "Writing" }, { id: "2", title: "Singing" }, { id: "3", title: "Dance" }],
array2 = [{ tags: "1", title: "USA", type: "text" }, { tags: "1,2,3", title: "Japan", type: "image" }, { tags: "2,3", title: "Japan", type: "image" }],
tags = array1.reduce((m, { id, title }) => m.set(id, title), new Map),
result = array2.map(o => ({ ...o, tags: o.tags.split(',').map(Map.prototype.get, tags).join() }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

JS compare two arrays with objects and remove duplicated by property name ES6 way

Wanted to compare two arrays with objects and remove duplicate by its property name, I have these two:
arr1 = [{
item:"apple",
description: "lorem"
},{
item:"peach",
description: "impsum"
}]
arr2 = [{
item:"apple", description: "dolor"
},{
item:"grape", description: "enum"
}]
and I wanted this result:
arr3 = [{
item:"peach", description: "impsum"
},{
item:"grape", description: "enum"
}]
I've tried this es6 approach but not working arr3 = arr1.filter(val => !arr2.includes(val));
Array.includes won't work because in javascript {} !== {}. You'll need another way like Array.every to check that every object in the other array doesn't have the same value of the property item as the current object. Also, you need to do both arr1.filter(...) and arr2.filter(...) and concat the results:
arr3 = [].concat(
arr1.filter(obj1 => arr2.every(obj2 => obj1.item !== obj2.item)),
arr2.filter(obj2 => arr1.every(obj1 => obj2.item !== obj1.item))
);
Example:
let arr1 = [{
item:"apple",
description: "lorem"
},{
item:"peach",
description: "impsum"
}];
let arr2 = [{
item:"apple", description: "dolor"
},{
item:"grape", description: "enum"
}];
let arr3 = [].concat(
arr1.filter(obj1 => arr2.every(obj2 => obj1.item !== obj2.item)),
arr2.filter(obj2 => arr1.every(obj1 => obj2.item !== obj1.item))
);
console.log(arr3);
See Set, Array.prototype.filter() and Spread Syntax for more info.
// Join Without Dupes.
const joinWithoutDupes = (A, B) => {
const a = new Set(A.map(x => x.item))
const b = new Set(B.map(x => x.item))
return [...A.filter(x => !b.has(x.item)), ...B.filter(x => !a.has(x.item))]
}
// Proof.
const output = joinWithoutDupes([{item:"apple",description: "lorem"},{item:"peach",description: "impsum"}], [{item:"apple", description: "dolor"},{item:"grape", description: "enum"}])
console.log(output)
a simple and faster sample:
arr1 = [{
item:"apple",
description: "lorem"
},{
item:"peach",
description: "impsum"
}]
arr2 = [{
item:"apple", description: "dolor"
},{
item:"grape", description: "enum"
}]
result = (counters = {}, arr1.concat(arr2).map(cur => (counters[cur.item] ? counters[cur.item]++ : (counters[cur.item] = 1), cur)).filter(cur => counters[cur.item] === 1))
console.log(result)

Categories

Resources