javascript - pick unique items from first array - javascript

Suppose I have two arrays of objects
const array1 = [{
listName: 'My top 5 Sci-Fi Movies',
listCreator: 'Anon',
listItem: 'The Fifth Element'
},
{
listName: 'My top 5 Sci-Fi Movies',
listCreator: 'Anon',
listItem: 'Cube'
}]
and
const array2 = [{
listName: 'My top 5 Sci-Fi Movies',
listCreator: 'Anon',
listItem: 'The Fifth Element'
},
{
listName: 'My top 5 Sci-Fi Movies',
listCreator: 'Dude',
listItem: 'Cube'
}]
I want to able to compare the two arrays and create a new array that only has unique members of array1, in this case
const uniqueArray = [{
listName: 'My top 5 Sci-Fi Movies',
listCreator: 'Anon',
listItem: 'Cube'
}]
I am using lodash library (but not necessary to solve this problem if not required) and I'd like to accomplish this in the fewest lines of code possible.

hello dear brother you use Hashset to fetch automatically Unique Data from list
HashSet<Integer>set = new HashSet<Integer>(list1);
List<Integer>list2 = new ArrayList<Integer>(set);
and then pass this Hashset to List again
ITS JAVA CODE BUT LOGIC IS SAME FOR EVERY LANGUAGE

After banging my head around the intertubes, I found a simple and elegant solution.
If I (using lodash) do
const arrNew = _.differenceWith(array1, array2, _.isEqual);
arrNew is a new array of unique items from array1. Hope this helps someone else out.
Would love to see if there's another more performant solution.
https://lodash.com/docs/4.17.15#differenceWith

Related

Why is .push() method giving duplicates

{
category: 'Music',
id: '625064c2e12f6dec240bdfcb',
correctAnswer: "Don't Leave Me This Way",
incorrectAnswers: [
'Ice Ice Baby',
'In-A-Gadda-Da-Vida',
'Rebirth of Slick (Cool Like Dat)'
],
question: 'What song did Thelma Houston have a hit with in 1976?',
tags: [ 'songs', 'one_hit_wonders', 'music' ],
type: 'Multiple Choice',
difficulty: 'hard',
regions: []
}
// Here is the response from the API...
const oldArray = quizData[number].incorrectAnswers;
oldArray.push(quizData[number].correctAnswer);
console.log(oldArray);
// Here i am pushing the correctAnswer into the incorrect Answer array but my console.log keeps repeating the correct answer data, Why is this happening? Am i pushing it wrong?
['An arrow', 'A lightning bolt', 'A bottle of wine', 'A Discus', 'A Discus', 'A Discus', 'A Discus', 'A Discus']
//Here is my console.log array.
// 'A Discus' keeps getting repeated 4 times, Same length of the present array, So the array has 7 values instead of just 3, What is going on?
use the spread operator to avoid duplications
console.log( [...new Set(oldArray)])
const list = ['Anemia', 'Heart Attack', 'Paralysis', 'Epilepsy', 'Epilepsy']
console.log( [...new Set(list)])

Compare between two arrays

While I was thinking in someway to compare between two arrays, accidentally for the first time something like this happens with me.. something worked with me for the first time without showing me any errors!
This is a very simplified visualization for an application I'm working on currently.
I have two arrays, one called options, the other is called correct.
so the options are options of some question, the chances are the chances of this question.
in this example two of the options are correct answers..
so what I have to do is to compare between this two arrays to check if it returns true (later) or if it's returning false (not included in the code).
could you please explain for me how this actually worked?
const options = ['facebook', 'twitter', 'tango', 'skype'];
const correct = ['twitter', 'skype'];
const trueIndexes = [];
options.forEach((cur, index) => {
correct.forEach((cur1, index1) => {
if (cur === cur1) {
trueIndexes.push(index);
}
});
});
console.log(trueIndexes);
There are nested forEach loops for each array, and during each inner loop there is a conditional test to ascertain if one element exists in the other. If so, the index of where the matching item exists in the other array is pushed to the new trueIndexes array.
Another way to write this is:
const options = ['facebook', 'twitter', 'tango', 'skype']
const correct = ['twitter', 'skype']
const trueIndices = correct.reduce((_trueIndices, correctItem) => {
let correctItemIndex = options.indexOf(correctItem)
if(correctItemIndex !== -1) _trueIndices.push(correctItemIndex)
return _trueIndices
}, [])
console.log(trueIndices)
or
const options = ['facebook', 'twitter', 'tango', 'skype']
const correct = ['twitter', 'skype']
const trueIndices = []
correct.forEach((correctItem) => {
let correctItemIndex = options.indexOf(correctItem)
if(correctItem !== -1) trueIndices.push(correctItem)
})
console.log(trueIndices)
Both of these alternate solutions should be faster.
Your code goes through each option and compares it to both correct values.
If they match the index of the option is added to the true indexes list.
So the comparisons are like follows:
'facebook' = 'twitter'? no
'facebook' = 'skype'? no
'twitter' = 'twitter'? YES -> add index to list
'twitter' = 'skype'? no
'tango' = 'twitter'? no
'tango' = 'skype'? no
'skype' = 'twitter'? no
'skype' = 'skype'? YES -> add index to list
As explained by others, you just iterate over all the combinations of these 2 arrays and collect the indexes where an option is in both arrays(in other words, if an option is true)
I just wanted to add that you should perhaps change your data structure so that options are stored with the questions...and correct answers are indicated by a flag so they don't need to be looked up.
For example:
const questions = [
{
id: 'social_1',
question: 'Which of these are popular social media sites?',
answers: [
{id: 'fb', label: 'Facebook', correct: true},
{id: 'skype', label: 'Skype', correct: false},
{id: 'twitter', label: 'Twitter', correct: true},
{id: 'yt', label: 'YouTube', correct: false},
]
}, {
id: 'cars_1',
question: 'Which of these are car brands?',
answers: [
{id: 'tesla', label: 'Tesla', correct: true},
{id: 'bmw', label: 'BMW', correct: true},
{id: 'twitter', label: 'Twitter', correct: false},
{id: 'yt', label: 'YouTube', correct: false},
]
}
];
https://jsfiddle.net/rainerpl/L438qjms/26/

Merge array of objects by key/value

I am trying to figure out the best way to map an objects id property that is within a multi-dimension array to object values that are within another array that share the same id.
As an example i have an array of genre_ids like so:
0: {id: 1, name: 'sci-fi'},
1: {id: 2, name 'comedy'},
2: {id: 3, name: 'action'}
And an array of tv_show_genre_ids which looks like:
0: {name: ..., genre_ids: [1, 4, 9]},
1: {name: ..., genre_ids: [2, 3, 4]},
I was trying to figure out the best way to retrieve a list of the genres name by its id.
I have managed to create a working solution so far but it feels incredibly dirty as i am performing multiple nested loops and i wasn't sure if there is a cleaner more declarative approach to my solution
Here is my approach which assumes i already have a list of genre ids and names (accessed within this.genres.
this.http.get('https://api.com/shows')
.subscribe((res: array <any> ) => {
this.shows = res.results;
this.shows.forEach(show => {
show.genre_names = '';
show.genre_ids.forEach(id => {
for (const [i, v] of this.genres.entries()) {
if (id == v.id) {
if (this.genres[i] && this.genres[i].name) {
if (show.genre_names === '') {
show.genre_names = this.genres[i].name
} else {
show.genre_names += `, ${this.genres[i].name}`;
}
}
}
}
})
});
});
Is there a better way of doing this as i seem to come across this type of problem quite often when trying to map ids from one object to another within multi-dimension arrays.
Any guidance would be greatly appreciated.
EDIT:
Here is an example of the Genre Data from the API af:
0: {id: 10759, name: "Action & Adventure"}
1: {id: 16, name: "Animation"}
And here is an example of the show data from the API:
0:
backdrop_path: "/ok1YiumqOCYzUmuTktnupOQOvV5.jpg"
first_air_date: "2004-05-10"
genre_ids: (2) [16, 35]
id: 100
name: "I Am Not an Animal"
origin_country: ["GB"]
original_language: "en"
original_name: "I Am Not an Animal"
overview: "I Am Not An Animal is an animated comedy series about the only six talking animals in the world, whose cosseted existence in a vivisection unit is turned upside down when they are liberated by animal rights activists."
popularity: 10.709
poster_path: "/nMhv6jG5dtLdW7rgguYWvpbk0YN.jpg"
vote_average: 9.5
vote_count: 341
I want to add a new property to the show object named genre_names which gets the genre name via the genre response.
Your best bet is to first convert your genres into a Map or an object to use as a lookup:
const genreLookup = new Map();
this.genres.forEach(genre => genreLookup.set(genre.id, genre));
Now when you process an array of shows, you don't have to loop through the genres multiple times:
this.shows.forEach(show => {
show.genre_names = show.genre_ids
.filter(id => genreLookup.has(id))
.map(id => genreLookup.get(id).name)
.join(', ');
});

Loop through array of objects, check for a matching parameter and add the matching object to new array

I'm new to JS and React and I'm a little stuck here. I've searched through SO but I'm having trouble finding a solution with an explanation that works.
Here are my arrays.
The first array is pretty simple.
[1, 3, 4,]
The second looks like this.
[
{
id: 1,
title: Title 1,
},
{
id: 2,
title: Title 2,
},
]
What I'd like to do is search the second array and if I can find an id that matches a value in the first array, add the object from the second array to third, new array.
I've tried a number of things and I'm sure there's a relatively easy way to do this with a forEach loop or lodash but I'm coming up blank.
Any help and explanations would be greatly appreciated.
Thanks,
Your second array is not valid. You have to wrap the string values with quotes.
You can use Array.prototype.filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
and Array.prototype.includes()
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
Try the following way:
var arr1 = [1, 3, 4,];
var arr2 = [
{
id: 1,
title: 'Title 1',
},
{
id: 2,
title: 'Title 2',
},
];
var res = arr2.filter(i => arr1.includes(i.id));
console.log(res);

How to weight items in a fuzzy search

Using Fuse.js, I need to weight individual item for a better ranking in search results. For instance, how do I make sure "Paris France" has the biggest score for a "Paris" query with the data below?
places = [{
name: 'Paris, France'
weigth: 10
},{
name: 'Paris, Ontario'
weigth: 2
},
{
name: 'Paris, Texas'
weigth: 1
}]
As far as I am aware, there are no methods built into Fuse.js to do this. The weight property is meant to be applied to properties which are being searched (in the options object), rather than to the object that is being searched (as seen in the example here.
What I might suggest is writing a function to sort this yourself. So once you get your results array back, after the search, perform an Array.sort() on it yourself (documentation here).
For example...
//Your places object
var places = [
{
name: 'Paris, Texas',
weight: 2
},
{
name: 'Paris, France',
weight: 10
},
{
name: 'Paris, Texas',
weight: 1
}
];
//Your search options
var options = {
keys: [
"name"
]
};
var fuse = new Fuse(places, options); // "list" is the item array
var result = fuse.search("Paris");
//Once you have got this result, perform your own sort on it:
result.sort(function(a, b) {
return b.weight - a.weight;
});
console.log('Your sorted results:');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.1.0/fuse.min.js"></script>

Categories