JavaScript: filter() Method Returning Back Original Array and Not Filtering - javascript

I have the following code below using the filter() array function.
arr = [12, 5, 8, 130, 44]
function test(arr) {
return arr.filter((element) => {
return element >= 10
});
}
console.log(test(arr))
My code is returning the original array ([ 12, 5, 8, 130, 44 ]) and not filtering at all. What am I doing wrong?
Note: I want to use the filter() method for this.

Filter returns a new array, so depending on how you are using your function, you most likely are looking at the original array, which you cannot do, you need to look at the filtered results.
let arr = [12, 5, 8, 130, 44]
function test(arr) {
return arr.filter((element) => {
return element >= 10
});
}
// The filtered results
console.log('The filtered array', test(arr))
// The original array
console.log('The original array', arr)
To modify the array in place you can use a while loop, and then splice the elements like this which will modify the array in place.
let arr = [12, 5, 8, 130, 44]
// Get the initial length of the array
let i = arr.length
// Loop backwards over the array as not to skip values when they get removed
while(--i) {
if(arr[i] > 10) continue
arr.splice(i, 1)
}
console.log(arr)
Instead of a while, you could also just assign the value back to the original array overwriting is original value.
let arr = [12, 5, 8, 130, 44]
function test(arr) {
return arr.filter((element) => {
return element >= 10
});
}
// Assign the result back to arr
arr = test(arr)
// The new value of arr
console.log(arr)

You code is missing a few things, but you are on the right track. Array.filter doesn't change the original array. Set a variable,var filter, and set it equal to the function test. Then console.log(filter(arr))

Related

Using JS every() method

I am trying to test if an array is sorted in ascending order using the JS every method: checking if every element is smaller than the next index.
I don't understand why my code below is not working.
const testArray1 = [1, 2, 3, 4, 5, 6];
const testArray2 = [25, 51, 32, 12, 15];
const isAscending = (element, index, array) => {element < array[index + 1]};
console.log(testArray1.every(isAscending));// expecting true, but getting false
console.log(testArray2.every(isAscending));// expecting false, getting false
I am aware that the sort method exists, this is for a school exercice.
You have two problems.
Your arrow function always returns undefined because it is missing a return statement.
You are comparing the last value in the array to undefined (e.g. when i is 5 for the first array, element is 6 and array[5 + 1] is undefined) which is always false so you need to implement a special case for that entry.

I pushed an element into an Array[0] position, however, it did not turned out as I intended. My element ended up at position Array[1], not Array[0] [duplicate]

I have a need to add or prepend elements at the beginning of an array.
For example, if my array looks like below:
[23, 45, 12, 67]
And the response from my AJAX call is 34, I want the updated array to be like the following:
[34, 23, 45, 12, 67]
Currently I am planning to do it like this:
var newArray = [];
newArray.push(response);
for (var i = 0; i < theArray.length; i++) {
newArray.push(theArray[i]);
}
theArray = newArray;
delete newArray;
Is there a better way to do this? Does JavaScript have any built-in functionality that does this?
The complexity of my method is O(n) and it would be really interesting to see better implementations.
Use unshift. It's like push, except it adds elements to the beginning of the array instead of the end.
unshift/push - add an element to the beginning/end of an array
shift/pop - remove and return the first/last element of an array
A simple diagram...
unshift -> [array] <- push
shift <- [array] -> pop
and chart:
add remove start end
push X X
pop X X
unshift X X
shift X X
Check out the MDN Array documentation. Virtually every language that has the ability to push/pop elements from an array will also have the ability to unshift/shift (sometimes called push_front/pop_front) elements, you should never have to implement these yourself.
As pointed out in the comments, if you want to avoid mutating your original array, you can use concat, which concatenates two or more arrays together. You can use this to functionally push a single element onto the front or back of an existing array; to do so, you need to turn the new element into a single element array:
const array = [3, 2, 1]
const newFirstElement = 4
const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]
console.log(newArray);
concat can also append items. The arguments to concat can be of any type; they are implicitly wrapped in a single-element array, if they are not already an array:
const array = [3, 2, 1]
const newLastElement = 0
// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement) // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]
console.log(newArray1);
console.log(newArray2);
var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]
With ES6, use the spread operator ...:
Demo
var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]
console.log(arr)
Another way to do that is through concat:
var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));
The difference between concat and unshift is that concat returns a new array. The performance between them could be found here.
function fn_unshift() {
arr.unshift(0);
return arr;
}
function fn_concat_init() {
return [0].concat(arr)
}
Here is the test result:
Quick Cheatsheet:
The terms shift/unshift and push/pop can be a bit confusing, at least to folks who may not be familiar with programming in C.
If you are not familiar with the lingo, here is a quick translation of alternate terms, which may be easier to remember:
* array_unshift() - (aka Prepend ;; InsertBefore ;; InsertAtBegin )
* array_shift() - (aka UnPrepend ;; RemoveBefore ;; RemoveFromBegin )
* array_push() - (aka Append ;; InsertAfter ;; InsertAtEnd )
* array_pop() - (aka UnAppend ;; RemoveAfter ;; RemoveFromEnd )
Using ES6 destructuring (avoiding mutation off the original array):
const newArr = [item, ...oldArr]
Without Mutating
Actually, all unshift/push and shift/pop mutate the source array.
The unshift/push add an item to the existed array from begin/end and shift/pop remove an item from the beginning/end of an array.
But there are few ways to add items to an array without a mutation. the result is a new array, to add to the end of array use below code:
const originArray = ['one', 'two', 'three'];
const newItem = 4;
const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+
To add to begin of original array use below code:
const originArray = ['one', 'two', 'three'];
const newItem = 0;
const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+
With the above way, you add to the beginning/end of an array without a mutation.
You have an array: var arr = [23, 45, 12, 67];
To add an item to the beginning, you want to use splice:
var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);
Cheatsheet to prepend new element(s) into the array
1. Array#unshift
const list = [23, 45, 12, 67];
list.unshift(34);
console.log(list); // [34, 23, 45, 12, 67];
2. Array#splice
const list = [23, 45, 12, 67];
list.splice(0, 0, 34);
console.log(list); // [34, 23, 45, 12, 67];
3. ES6 spread...
const list = [23, 45, 12, 67];
const newList = [34, ...list];
console.log(newList); // [34, 23, 45, 12, 67];
4. Array#concat
const list = [23, 45, 12, 67];
const newList = [32].concat(list);
console.log(newList); // [34, 23, 45, 12, 67];
Note: In each of these examples, you can prepend multiple items by providing more items to insert.
If you need to continuously insert an element at the beginning of an array, it is faster to use push statements followed by a call to reverse, instead of calling unshift all the time.
Benchmark test: http://jsben.ch/kLIYf
Using splice we insert an element to an array at the begnning:
arrName.splice( 0, 0, 'newName1' );
If you want to push elements that are in an array at the beginning of your array, use <func>.apply(<this>, <Array of args>):
const arr = [1, 2];
arr.unshift.apply(arr, [3, 4]);
console.log(arr); // [3, 4, 1, 2]

console.log vs return: different results (JS)

I don't understand why the code below gives different results in console.log inside the filter function and in the return function:
function expandedForm(num) {
let arr = num.toString().split('').reverse().filter(function(el, ind){
console.log("iter:"+ el * Math.pow(10,ind));
return (el*Math.pow(10,ind))
});
console.log(arr);
return arr;
}
expandedForm(402);
gives this:
iter:2
iter:0
iter:400
[ '2', '4' ]
=> [ '2', '4' ]
EDIT:
Apparently, I haven't been clear enough. To be straightforward, why I get 400 in console.log and 4 in filter? So the question regards more the evaluation of the expression el * Math.pow(10,ind)
Because filter on array does not manipulate the elements in array
For eg:
const arr = [1, 2, 3];
const newArr = arr.filter(e => {
const newElement = e * 100;
return newElement;
}
Here we expect newArray to be [100, 200, 300] but we receive it [1, 2, 3].
Reason - return value from filter is just for true/false concern, it does not actually return the value. This is the reason why you are not getting value for 0.
You can try below code if you want an output [2, 0, 400]
const arr = num.toString().split('').reverse().map((el, ind) => {
return (el * Math.pow(10,ind));
});
If you want an output as [2, 400],
const arr = num.toString().split('').reverse().map((el, ind) => {
return (el * Math.pow(10,ind));
}).filter(e => e);
num.split('') return one array ['2', '0', '4'],
num.split('').filter(function(){ return handler()}) return the elements when hander() is true, then the second selmement is '0', its final result is 0, so it will not keep this element.
Finnally, the reuslt is ['2', '4']
As Array.prototype.filter() defined: (Look into the description on the parameter=callback).
Syntax
var newArray = arr.filter(callback[, thisArg])
Parameters
callback
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise, taking three arguments:
element
The current element being processed in the array.
indexOptional
The index of the current element being processed in the array.
arrayOptional
The array filter was called upon.
thisArg Optional
Optional. Value to use as this when executing callback.
You need to read the documentation of .filter function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
A new array with the elements that pass the test. If no elements pass
the test, an empty array will be returned.
It doesn't matter what you return inside from filter function all it cares about if its true of false for each index. As you have 0 in 402 it skips the middle element and returns only elements which are >0

Reducing array of items into a single array list [duplicate]

This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 6 years ago.
Below is my array if items that I want to reduce it to a single list of arrays..
var input=[
[
2
],
[
3,
13
],
[
4,
14
],
[
5,
15,
25,
35
]
]
var output=[
2,
3,
13,
4,
14,
5,
15,
25,
35
]
My code:
function reduceArray(item){
for(var i=0;i<item.length;i++){
return i;
}
}
var result=result.map((item)=>{
if(item.length>0){
return reduceArray(item);
}else{
return item;
}
})
which produces the same result.Can anyone please figure out where I'm doing wrong or any other approach to achieve this..Thanks
input.reduce(function(a, x) { return a.concat(x); });
// => [2, 3, 13, 4, 14, 5, 15, 25, 35]
reduce sets the accumulator to the first element (or a starting value if provided), then calls the function with the accumulator and each successive element. The function we provide is concatenation. If we say input is [a, b, c], then the above command will be equivalent to a.concat(b).concat(c). [concat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) produces a new array by smushing two or more arrays together.
EDIT: Actually, there is another possible answer:
Array.prototype.concat.apply(input[0], array.slice(1));
// => [2, 3, 13, 4, 14, 5, 15, 25, 35]
This directly calls concat with multiple arguments; if input is again [a, b, c], then this is equivalent to a.concat(b, c). apply calls a function with a given receiver and arguments; slice will give us just a part of the array, in this case everything starting from the first element (which we need to chop off since it needs to be the receiver of the concat call).
One liner would be
input = [[2],[3,13],[4,14],[5,15,25,35]];
[].concat.apply([],input);
You can use lodash's flattenDeep()
_.flattenDeep([1, [2, [3, [4]], 5]]);
// → [1, 2, 3, 4, 5]
User concat.check this for more information http://www.w3schools.com/jsref/jsref_concat_array.asp
var input=[[2],[3,13],[4,14],[5,15,25,35]];
var output=[];
for(var i = 0; i < input.length; i++)
{
output = output.concat(input[i]);
}
console.log(output);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
use concat is the perfect way
The concat() method is used to join two or more arrays.
This method does not change the existing arrays, but returns a new array, containing the values of the joined arrays.
var newArr = [];
for(var i = 0; i < input.length; i++)
{
newArr = newArr.concat(input[i]);
}
console.log(newArr);

How do I get this 'Sorted Union' function to work using Array.concat, in javaScript

I am going through this exercise on FCC which requires the following:
Write a function that takes two or more arrays and returns a new array
of unique values in the order of the original provided arrays.
In other words, all values present from all arrays should be included
in their original order, but with no duplicates in the final array.
The unique numbers should be sorted by their original order, but the
final array should not be sorted in numerical order.
This is my code:
function uniteUnique(){
var elm, exists = {},
outArr = [],
arr = [],
args = Array.prototype.slice.call(arguments);
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
for(var i =0; i<arr.length; i++){
elm = arr[i];
if(!exists[elm]){
outArr.push(elm);
exists[elm] = true;
}
}
return arr;
}
My problem centers around this line.
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
I'd like all the arguments/arrays to go through the filter method and then get concatenated, any help would be appreciated!
Boolean will not filter unique items, it will simply return Boolean(arg) value which is not the intended one.
Replace
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
with
args.forEach(function(arg) {
arr.concat(arg.filter(function(val){
return arr.indexOf(val) == -1;
}));
});
This will only concatenate array items which are unique
Well may be you prefer the following single liner functional approach instead;
var getUniques = (...a) => a.reduce((p,c)=> p.concat(c)).reduce((p,c) => {!~p.indexOf(c) && p.push(c); return p},[]);
document.write("<pre>" + getUniques([1,2,3],[3,4,5],[3,4,5,6,7,8],[0,1,2,3,4,5,6,7,8,9]) + "</pre>");
The getUniques function returns an array of all uniques in the order of appearance. Note that there is no arguments object in the arrow functions but the ...rest parameters of ES6 work just as well for that purpose. Even if you don't like the functional approach the logic behind may influence you to implement the same functionality with conventional functions and for loops.
And an even more simplified version of the above one is as follows
var getUniques = (...a) => a.reduce((p,c) => {c.forEach(e => !~p.indexOf(e) && p.push(e)); return p});
document.write("<pre>" + getUniques([1,2,3],[3,4,5],[3,4,5,6,7,8],[0,1,2,3,4,5,6,7,8,9]) + "</pre>");
function union(arrays) {
const u = arrays.reduce(function(acc, iVal) {
return acc.concat(iVal);
})
return [...new Set(u)];
}
var arr1 = [5, 10, 15];
var arr2 = [15, 88, 1, 5, 7];
var arr3 = [100, 15, 10, 1, 5];
console.log(union([arr1, arr2, arr3])); // should log: [5, 10, 15, 88, 1, 7, 100]

Categories