var data = [1, 2, 3, 5, 2, 1, 4];
// iterate over elements and filter
var res = data.filter(function (v) {
// get the count of the current element in array
// and filter based on the count
return data.filter(function (v1) {
// compare with current element
return v1 == v;
// check length
}).length == 1;
});
console.log(res);
I understand all the line in this code, but I don't understand how it can detect the length==1.
(My opinion) Because it loop though every single element in the array and return boolean value either true or false so how it can use to detect the length?
This code is to get the array element that only appear once in the array.
The return true is not to return the boolean, but when you return true from inside a filter, that item gets added to the resulting array of filter function.
The process here is called chaining of methods. On line 11, first, the filter is applied to the data array, then the .length method is applied to the result of the filter, which will be an array of equal length or less than the number of elements in the data array. Then finally only once the return is called, which will be a boolean used for the outer filter.
Another example:
function reverseString (inputString) {
return inputString.split("").reverse().join()
}
In the above example, the function returns after the split, then reverse on the split's result, then join on the reverse's result. The final resulting string is only returned.
Don't think about it as lines of code. Split each segment of code into its true meaning my padawan
data.filter(function (v1) {
// compare with current element
return v1 == v;
// check length
})
filters the data array to return an array of elements from data such that every element in it is equal to v
By checking if its length is 1, you want to return true if the the array has only 1 element.
So,
var res = data.filter(function (v) {
// return true if there is only 1 element in data which is equal to v
});
Which basically means, we are filtering data, and returning a new array where every element is such that it has only one occurrence in the array.
The function for filter returns a boolean, but filter itself returns an array.
So, for example:
array.filter(function(element) { return element >= 0; });
says that the function function(element) { return element >= 0; } will be applied to each element in array. Then, if the result of the function is true, that element will exist in the final, filtered version of array (which is what the filter function returns), or will not exist if the result is false.
In effect, all negative numbers from array will be filtered out because they return false.
What your code is saying is the following: For every element in data, filter data to keep only the elements equal to the current one. If this filtered list has only one element, then it can only be our current element. Therefor this element exists only once and should be kept in the final result, so we return true if .length == 1. In the end, once this is done for every element, filter is smart enough to convert those results of true and false into an array of the elements that produced true and leave out those that produced a false.
I will describe the filter method step by step in detail.
First, it takes a condition. then it returns an array with all values which passed the condition successfully
so think about this block of code as a condition
return data.filter(function (v1) {
// compare with current element
return v1 == v;
// check length
}).length == 1;
so let's take the first part of the condition
data.filter(function (v1) {
// compare with current element
return v1 == v;
// check length
})
and let's say we gonna start with the first element 1 , so how many times v1 === v ? the answer is two times so it will return this array [1, 1]
so forget the condition we wrote in the first lines and think about it like that [1,1].length === 1.
So [1,1].length === 1 will return false
The same will happen with number 2. so let's talk about the number 3. it will be [3].length === 1 which is true which will go to the upper level and that's why the res will be finally [3, 5, 4]
Related
I need some help with this, I'm stuck in JS Arrays & Loops, I don't know why this is telling me that if the function is empty is not returning "0".
function sumArray (numbers) {
// your code
var numbers = [1, 2, 3, 4];
if (numbers !== undefined) {
const sum = numbers.reduce((a,b) => a+b, 0)
return sum
}
else if ( numbers === []);{
return 0
}
}
sumArray();
I tried to return 0 when the array is empty, but I' don't know what I'm missig.
Beside the missing code, you could just return the result of reduce.
return numbers.reduce((a, b) => a + b, 0);
Some other annotations:
Do not redeclare and assign numbers, because you the the array as parameter.
Do not check against undefined here, because you get always an array as parameter.
You can not check an empty array with comparing another (literally) empty array, because arrays are objects and you compare different object references. For checking if an array is empty, take Array#length property and compare against zero.
The first issue is that you have a line ensuring that numbers is always an array containing 1,2,3,4; so the empty condition will never be met. So that line needs to be removed.
A second issue is that you have an extraneous semicolon that is subtly changing the logic.
The following logic will run the empty statement if numbers references the array object you just created using the array literal synax ([]); then a block will be evaluated outside of the else..if block, returning zero.
else if ( numbers === []);{
return 0
}
If you want to check if an object is an array you can use Array.isArray(foo).
If you want to check if an array is empty, you can test its length (if(myArray.length === 0) ...)
So what you probably meant to write was:
else if (numbers.length === 0) {
return 0
}
...but it turns out that the reduce code will work correctly if the array is of zero length; so that bit of logic is not necessary.
What you want is something like this:
function sumArray(numbers) {
if (!numbers) return 0;
return numbers.reduce((a,b) => a + b, 0);
}
console.log(sumArray())
console.log(sumArray([]))
console.log(sumArray([1, 2, 3, 4]))
I've been confused with how _.reduce works here all day.
_.every = function(collection, iterator) {
var check = iterator || _.identity;
var result = _.reduce(collection, function(accumulator, val) {
return accumulator && !!check(val);
}, true);
return result;
};
console.log(_.every([true, false, 1, 2, 3, 4], _.identity)); // ===> false
So as i understand _.reduce it goes through the collection and for each element the iterator(accum, val), is called on each element in the array, and then return the accumulator, but I don't understand what line 4 is doing: return accumulator && !!check(val);. How come it doesn't check false, set that as the accumulator, then go to check 1 and set that as the accumulator, then move on to the rest of the array until it gets to 4 which would means the last accumulator is true? Sorry if this doesn't make sense.
.every is basically a compound &&. The result should only be true if every single element also results in true.
So in this line of code...
return accumulator && !!check(val);
...accumulator is the value so far.
If accumulator is true, then everything's fine so far. It will call check on the current element of the array, convert the result to a boolean, and return that. The returned value becomes the accumulator on the next step.
If accumulator is false, it's because something earlier in the array returned false. That means we've already failed, and there's no need to keep checking the rest of the array. Even if something later in the array returns true it won't matter. Thus this expression will return false, and not even bother calling check.
I am trying to check is every element is array has truthy value.
But I am confused when testing an array has some empty value.
var arr = [];
arr[10] = 1;
arr; // [empty x 10, 1];
arr.every(item => Boolean(item)); // true ???
Boolean(arr[0]); // false ???!!!
this is what I get when running the code above on chrome devtool console
every, some, map, filter, and most of the others only visit array entries that exist, they don't visit the gaps in sparse arrays like yours. So the result is only based on checking the values of elements that actually exist.
You can see that if you step through the callback or add logging to it:
var arr = [];
arr[10] = 1;
arr.every((item, index) => {
console.log(`Visited index ${index}, item = ${item}`);
return Boolean(item);
});
// =>
// Visited index 10, item = 1
// Note that 0-9 are gaps:
console.log(`0 in arr? ${0 in arr}`); // false
console.log(`9 in arr? ${9 in arr}`); // false
console.log(`10 in arr? ${10 in arr}`); // true
As you can see, the every callback in that only outputs one line because it's only called once.
If you want that array to actually have undefined for elements 0 through 9, you could use fill; then every would test element 0 and return false since Boolean(undefined) is false:
var index = 10;
var arr = Array(index + 1).fill();
arr[index] = 1;
console.log(arr.every(Boolean)); // false
Most array operations don't operate on unassigned indexes in sparse arrays. From the MDN documentation:
callback is invoked only for array indexes which have assigned
values. It is not invoked for indexes which have been deleted, or
which have never been assigned values.
You only have one index with an assigned value which is truthy, so your call to every() will return true.
I'm looking at an exercise and having trouble understand how the following works ( I'm trying to remove duplicates from an array)
var arr = ['a','b','c','a','b','d','e','f'];
var uniqueArray = arr.filter(function(item,pos){
return arr.indexOf(item) == pos;
});
My attempt to understand
Here item takes on all of our values in arr. Lets go through an iteration
First item = 'a' and pos = 0. Ok. now we want to only filter on the basis of if the index of 'a'is the same as 0
Here indexOf(a) == 0.
Great! this is true, lets put it in the new array.
Now lets move forward to where we see a again, namely at pos = 3
arr.indexOf(a) == 3
Wait... Doesent this meet our requirement as well? How does this even remove duplicates?
indexOf returns just one integer value, and it is the index of the first found item. So, when pos is 3 (and the item is a), indexOf will return 0 (because the first index of a is 0), 0==3 is false and the element will be removed.
Then, when the pos is 4 (and item is b), indexOf returns 2, the index of the first found b.
As for the objects, they can't have duplicate keys. Each new key will automatically overwrite the old one, so there won't be any duplicates.
Look:
var obj = {a:1, a:3, b:2,c:5,b:4};
console.log(obj)
nicael is right. indexOf(item) is just a function that goes through the array and looks for the first time item appears in the array, and returns the position in the array. In your example, if there is an a at 0 and a at index 3, then indexOf('a') will return position 0, while the value of pos is 3, so the filter returns false.
FOLLOW UP:
indexOf() has another parameter called the fromIndex, which lets you start the search from a position other than the beginning of the array. In this case, you can specify to skip over the first time 'a' occurs by doing arr.indexOf('a', 1) which starts the search at position 1, not 0. In this case the function would return true since the next 'a' is at position 3.
Can I use filter on an object?
No, because filter is a specific function of an Array object. You can get the keys of the object by doing a filter on Object.keys(myObject) since keys() returns an array.
Using your example:
var keyArray = Object.keys(myObject); //object can't have duplicate keys
keyArray.filter(function(item, index) {
return keyArray.indexOf(item) == index; //will never be false
});
Hashtable is the best way to eliminate the redundant values
Here is the code :
char arr[] = ['a','b','c','a','b','d','e','f'];
//it will contains all 26 places as zero (A - Z)
char hashArray[26]={0}
int i; //for iteration;
for(i=0;arr[i]!='\0';i++)
{
//it will subtracte the ascii value of the letter
//from 'a' so that we have the values from 0 to 26)
hashArray[arr[i]-'a']=arr[i];
}
for(i=0;i<26;i++)
{
if(hashArray[i]!=0) //to Ensure the positon has the character
{
printf("%c",hashArray[i]);
}
}
Suppose I've got a nested array:
// 3rd element in sub-array indicates a number of repeats
var list = [["a","b",1],["a","d",1],["a","b",1],["c","d",1]];
Task is to remove identical sub-arrays and increase number in single unique sub-array, which would indicate the number of repeats, so that above example would transform into smth like:
[["a","b",2],["a","d",1],["c","d",1]]
What would be the most efficient way to achieve this?
Currently I'm trying smth like this:
var list = new Array();
// Sort by second element
list.sort(function(a,b) {
return a[1] > b[1];
});
function collateList(element,index,array){
// if 1st&2nd element of subarray equals to 1st&2nd element of next subarray
if (array[index[0]]==array[index[0]+1] && array[index[1]]==array[index[1]+1]){
// increase 3rd element of subarray by 1
array[index[2]] = array[index[2]+1];
// remove next element from an array
array.splice((index+1),1);
}
}
list.forEach(collateList);
Let us first define the function determining if two subarrays are to be combined, in this case that their first two values are the same:
function match(e1, e2) { return e1[0]===e2[0] && e1[1]===e2[1]; }
Now let us define a function which finds a matching element in an array, based on a matching function, and returns its index. This is the same as Array.prototype.findIndex, were it defined.
function find(a, v, fn) {
for (i in a) { if (fn(v, a[i])) {return i;} }
return -1;
}
Now we feed the input through a reduce to create an new array with counts updated and duplicates removed:
list.reduce( // Boil down array into a result
function(result, elt) { // by taking each element
var prev = find(result, elt, match); // and looking for it in result so far.
if (prev !== -1) { // If found
result[prev][2]++; // increment previous occurrence;
} else { // otherwise
result.push(elt); // include as is in the result.
}
return result; // Use this result for next iteration.
},
[] // Start off with an empty array.
)