array name stays and it duplicates and repeating this process just clogs the list up.
Thank you.
setListItems(contents.data);
console.log(contents.data);
To convert the array contents.data to Set, do this:
const setData = new Set(contents.data);
That will remove all the duplicate items.
Then to convert it back, do this:
const uniqueArray = Array.from(setData);
The above will only work if the original array (contents.data) consisted of primitive values. If it was an array of objects then this will not work as-is and will require some changes.
Taken straight from MSDN:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#remove_duplicate_elements_from_the_array
// Use to remove duplicate elements from the array
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
Related
I'am doing some JavaScript exercises and I stumbled upon this one "Write a JavaScript program to filter out the non-unique values in an array."
I tried and found a solution, which worked but it was to cumbersome. A better answer, according to the site, is the following:
const filter_Non_Unique = arr =>
arr.filter(l => arr.indexOf(l) === arr.lastIndexOf(l));
console.log(filter_Non_Unique([1,2,3,4,4,5,6,6])) // 1,2,3,5
Now I recked my head trying to understand why this solution works but I still don't get it.
Can somebody explain to me?
Thanks in advance.
If the element only occurs once in the array, the first index will be the same as the last index, the index will not change for both calls.
eg:
const arr = [1,2,3,4,4,5,6,6]
console.log(arr.indexOf(5))
console.log(arr.lastIndexOf(5))
Since both of of these functions return the same index, filter will keep the element in.
On the other hand if there are multiple values, those values will have different indexes, so the filter will return false, and remove it from the array:
const arr = [1,2,3,4,4,5,6,6]
console.log(arr.indexOf(4))
console.log(arr.lastIndexOf(4))
I've answered a question similar to the one you solved here, you could try that logic too.
Beside of the indexOf/lastIndexOf approach which needs a lot of iterating the array, you could take a two loop approach.
By getting an array of single items by using a hash table and three states, like
undefined, the standard value of not declared properties of an object,
true for the first found value,
false for all values who are repeated in the array.
Then filter by the value of the hash table.
const
filterNonUnique = array => {
var hash = {};
for (let v of array) hash[v] = hash[v] === undefined;
return array.filter(v => hash[v]);
}
console.log(filterNonUnique([1, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 7]))
For a reason specific to this application an array of data or nulls is used to display a list of forms. The difference is based on whether data was provided by a service or manually added, where null indicates everything was manually added via
a button not a service.
So ignoring the use case of an array of nulls it turns out that [null, null, null].splice(0, 1); removes the null at index 2 instead of 0 based on entering values into the different forms displayed based on the array length, and then seeing who disappears on delete.
It can be made to work by adding something unique like { index: theIndex } to the array instead of null. So splice now works correctly removing the item at index 0 instead of 2, but now I'm curious what splice does under the covers that it can't remove an index regardless of its value compared to the other indices.
Can anyone explain what splice is doing? Based on the spec for splice I don't really see why this happens.
(This follows from the comments in the question but is too large to be a comment).
So I think you are having a conceptual misconception (^^). Look at this examples:
let a = [1, 2, 3]
a.splice(0, 1) // => 1
a // => [2, 3]
let b = [1, 2, 3]
delete b[0] // => true
b // => [<1 empty slot>, 2, 3]
The splice function modifies the array in-place. Note that, although we spliced the first element, we got as a result an array of two elements.
Look now at this example
let a = [1, 1, 1]
a.splice(0, 1)
a // => [1, 1]
let b = [1, 1, 1]
b.splice(2, 1)
b // => [1, 1]
We are deleting the first element from a and the last from b, but of course there's no way of telling so just looking at the result.
In the case with the nulls, the same thing is happening. Some library (Angular) is trying to figure out which element you deleted, but there's no way of knowing. This is because null === null.
Now if you use an array of empty objects, for example, there would be a way of knowing. Since {} !== {}---because each time you cast a {} you are creating a unique object---, then you could know which element is missing in an array of empty objects. The case is similar with the array [1, 2, 3].
let a = [{}, {}, {}] // lets imagine that each object has a unique id
// and we have [{}#1, {}#2, {}#3]
let [obj1, obj2, obj3] = a
obj1 === obj2 // => false, because they have different ids.
a.splice(0, 1)
a // => [{}#2, {}#3]
a.includes(obj1) // => false, because {}#1 is no longer in a
So an alternative to using an array of nulls, would be to use an array of empty objects. I think that is why the code works for you when you use objects like { index: theIndex }. But of course all depends on how smart Angular is. I bet there is a more native way of deleting an element, as #KaiserKatze points out, "it's always a bad idea to directly remove or add elements in the array if it maps to your model."
You have to understand that when you are splicing the array you're only doing that--removing an element from an array. You're not removing the "form element" when splicing the array. Instead, some foreign code is reading the array and trying to figure out --under the hood-- what you intended to do.
I tried searching using many different keywords but I'm unable to get the result I'm looking for.
I've created a table with five values as such: 10, 3, 5, 4, 2
I have a row on top of the table which shows the rank.
So, above 10, it should say "5"
Above 3, it should say "2"
Above 5, it should say "4"
Above 4, it should say "3"
Above 2, it should say "1"
I can take care of the tabular column. It is the main script that I don't understand.
I thought I can create a duplicate array of the original one and sort the duplicate - Then compare both original and duplicate to rank them. It turns out that when I sort the duplicate array, the original is also sorted.
I thought I can create 2 duplicate arrays and not touch the original one. It still sorts all of the arrays. How can I do this then?
It sounds like you are looking for how to clone or deep copy an array. When you do something like:
var a = [5,4,3,2,1]
var b = a;
Array b is set to refer to array a. If you, however, take a slice or do something else to get a copy of the data (not something refering to the actual structure), you can clone the array. So something like:
var a = [5,4,3,2,1]
var b = a.slice(0);
will give you an array b that won't change if you change a. See articles like this for more information.
You can duplicate the array using spread. From there you can do a simple sort() to get the rank you're trying to achieve:
const arr = [10, 3, 5, 4, 2];
const sortedArr = [...arr].sort((a,b) => a > b);
console.log(sortedArr);
I have this example:
var array=[0.1,2,3,4,6,7,8,9]
What I want is to store it in a variable only those values
var newArray=[3,4,6,7,8,9]
Of course, this must be dynamic ... regardless of the number of elements to store more than the first 3 items.
You need to use JavaScript's slice:
var array = [0.1,2,3,4,6,7,8,9];
var newArray = array.slice(2);
// [3, 4, 6, 7, 8, 9]
Read more here: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
Usage: arr.slice([begin[, end]])
slice does not alter. It returns a shallow copy of elements from the original array. Elements of the original array are copied into the returned array.
I have 3 separate arrays and I'm looking to load them all into to a single array. Am I able to use .push() several arrays into one? Is something like this possible?
var activeMembers=[]; // Active Users
var noactiveMsg=[]; // Non-Active Users with a Pending Message
var noactiveNomsg=[]; // Non-Active Users without a Pending Message
var chatCenterMembers=[]; // Final Array of Chat Center Members
chatCenterMembers.push(activeMembers).push(noactiveMsg).push(noactiveNomsg);
Is there a way to chain .push()?
You're looking for the (vanilla) JavaScript method Array.concat().
Returns a new array comprised of this array joined with other array(s) and/or value(s).
Example, following your code:
chatCenterMembers = chatCenterMembers
.concat(activeMembers)
.concat(noactiveMsg)
.concat(noactiveNomsg);
chatCenterMembers.push(activeMembers,noactiveMsg,noactiveNomsg)
This question is quite confusing. First of all, the question seems to be asking for a way to combine multiple arrays into one single array containing the elements of all the arrays. However, the accepted answer provides a solution for creating an array of arrays. Since the text in the question suggests merging the elements of multiple arrays into one array while the code example uses push with arrays as arguments, it's quite ambigious what the OP wants.
Furthermore, several answers have suggested using concat. While that fulfills the requirement of returning the resulting array after adding the provided element, and is fine for small sets of data and/or where performance and memory is not an issue, it's inefficient if dealing with large arrays, since each concat operation will allocate a new array, copy all the elements of the old array into it, then copy all the elements of the provided array into it, and dereference the old array (as opposed to simply adding elements to the same array object).
Consider calling concat N times, adding C elements each time:
allocate new array, copy C elements
allocate new array, copy 2 * C elements
allocate new array, copy 3 * C elements
...
A different approach would be to create your own method, either as a separate function or adding it to the Array prototype:
Array.prototype.append = function(e) {
this.push(e);
return this;
}
With this, you could do
[1, 2, 3].append(4).append(5).append(6)
without allocating more than one array object in total.
It could perhaps also be mentioned that with ES2015, the spread operator can be used to add all the elements of an array to another array using push:
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
arr1.push(...arr2); // arr1 is now [1, 2, 3, 4, 5, 6]
This will however not fulfill the requirement of returning the resulting array for chaining, but the append method above could be used to merge multiple arrays like this:
chatCenterMembers = activeMembers.append(...noactiveMsg).append(...noactiveNomsg);
You can do it instead with .concat().
var chatCenterMembers=[];
chatCenterMembers = chatCenterMembers.concat(activeMembers, noactiveMsg, noactiveNomsg);
Since on one else has posted it:
var chatCenterMembers = activeMembers.concat(noactiveMsg, noactiveNomsg);
push AND unshift chaining
I actually came here looking for both but didn't see any good answer so far for unshift so I'll note that here as well.
push chaining is straight forward
const list = ['hi', 'there']
.concat(['buddy'])
// list is now ['hi', 'there', 'buddy']
but unshift chaining is weird
// need to use concat + map to do unshift chaining
const list = ['hi', 'there']
.concat(['buddy'])
.map((e, i, a) => i == 0 ? a[a.length - 1] : a[i-1])
// list is now ['buddy', 'hi', 'there']
As you can see using map there is a 3rd param given for the array you are using so this gives you power to do all sorts of odd things.