I am trying to solve a problem I'm facing in Javascript, I am totally new to JS. This is my code:
function filterOutStringfromArr(array) {
var arr = []
for (var i = 0; i < array.length; i++) {
if (typeof array[i] === 'number') {
arr[i] = array[i]
}
}
console.log(arr)
}
filterOutStringfromArr([1,2,'A','B',123])
when I run this, I get this result: [ 1, 2, <2 empty items>, 123 ].
I know this is happening because the length of my array is 5. But I want to append just the filtered value to the empty array arr[]. How can I do this?
function filterOutStringfromArr(array) {
var arr = []
for (var i = 0; i < array.length; i++) {
if (typeof array[i] === 'number') {
arr.push(array[i])
}
}
console.log(arr)
}
filterOutStringfromArr([1,2,'A','B',123])
MDN link that is pretty good
You should use push that will append to the end of an array. By inserting the found element into spot i you are going from index 3 to 5 thus the empty elements.
I suggest to use the Array.prototype.push() method.
function filterOutStringsfromArray(array) {
var arr = [];
for (let i = 0; i < array.length; i++) {
if (typeof array[i] === 'string') {
arr.push(array[i]);
}
}
return arr;
}
filterOutStringfromArr([5, 2, 'h', 2, 's', 2]) // Expected Output: ['h', 's']
Filter method will solve your issue.
function filterOutStringfromArr(array) {
const newArray = array.filter(item => {
if (typeof item === 'number') {
return item;
}
})
console.log(newArray);
}
filterOutStringfromArr([1,2,'A','B',123])
Personally i would just use a normal array filter function and test the condition. let native array.filter function do the work for you. The below will filter the array and return a new array (not modify the existing array).
function filterToArrayOfNumbers(arrayElement) {
return typeof arrayElement === 'number';
}
console.log([1,2,'A','B',123].filter(filterToArrayOfNumbers));
arr[i] = array[i] // <------------ your issue
i is still being incremented, so when you are looking at your last number 123, (index 4), it will set the new array at index 4 (leaving 2 and 3 empty)
rather than setting it explicitly, you can do arr.push(array[i])
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
Related
This question already has answers here:
How to compare arrays in JavaScript?
(61 answers)
Closed 3 months ago.
I'm trying to make a function that takes an array as input and a target, and then iterates the array to check if the current index is equal to the target. If so, it will splice the current index from the array.
Everything works fine so far, however when i implement an if statement to check if the index is at the end of the array and then check if the result array is equal to the input array. I really don't know why this is taking me so long it's kind of embarrassing... Here's my code:
let array = ['fox', 'tiger', 'elephant', 'jaguar', 'wolf', 'deer', 'hog', 'dhole', 'leopard', 'eagle', 'bear'];
const splice = (arr, target) => {
//creates empty result array
let result = [];
//iterate through the input array and push each item to the result array
for(let i = 0; i < arr.length; i++) {
result.push(arr[i]);
}
let j = 0;
//iterate through result array
while(j < result.length) {
if (result[j] === target) {
result.splice(j, 1);
}
//i have tried this multiple times with the if statement in and out of the loop
if (j === result.length && result === arr) {
//throw new Error(`${target} was not found in the array`);
console.log({result, arr, j});
return 'equal';
} else if (j === result.length && result !== arr ) {
console.log({result, arr, j});
return 'different';
}
j++;
}
};
//should return 'equal' but returns 'different'
console.log(splice(array, 'turtle'));
//should return 'different' but returns undefined
console.log(splice(array, 'bear'));
Hope this help
const splice = (arr, target) => {
//creates empty result array
let result = [];
//iterate through the input array and push each item to the result array
for(let i = 0; i < arr.length; i++) {
result.push(arr[i]);
}
let j = 0;
//iterate through result array
while(j < result.length) {
if (result[j] === target) {
result.splice(j, 1);
/* since you modified the length of result array here,
u can simply check the length of result array
with the original array to see if there's a different */
}
// result === arr will always resolve to fasle as they are not the same object, so check the length instead
if (j === result.length && result.length !== arr.length) {
//throw new Error(`${target} was not found in the array`);
console.log({result, arr, j});
return 'equal';
} else if (j === result.length && result.length === arr.length ) {
console.log({result, arr, j});
return 'different';
}
j++;
}
// a better way of doing it is to move the if check outside of while loop to avoid it run multiple time
if (result.length !== arr.length) { // different length, that mean we found the target and the result array got modified
console.log({result, arr, j});
return 'equal';
} else {
console.log({result, arr, j});
return 'different';
}
};
Here you can use this logic to compare two arrays are same or not :
let arr1 = [1, 2, 3, -2, null];
let arr2 = [1, 2, 3, -2, null];
let bool = true;
let i;
for (i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
bool = false;
break;
}
}
if (arr1[i] === arr2[i]) bool = true;
if (arr1[i] !== arr2[i] || arr1.length !== arr2.length) bool = false;
if (bool) console.log("same");
else console.log("different");
As others told you in comments, since arrays are object in JavaScript, you cannot compare them with a simple ===.
To compare 2 arrays, first, you have to decide what do you means by arr1 === arr2.
For example:
does [A,C,B] concider equals to [A,B,C]?
how about [A,B,C, ]?
Lets say you need the two arrays to have...
1.) same length,
2.) index value must matches.
you can do something like this:
const arr1 = [1,2,3,"A"];
const arr2 = [1,2,3,"A"];
function compareArr(A,B) {
return (A.length === B.length) && A.every((v,i) => B[i] === v)
}
console.log(compareArr(arr1,arr2))
I've been trying and searching how to loop through the params to check if those already exist in an array, i haven't got it fully working but when there is a duplicate value it dose not return at all.
The idear is pass multiple values is param then loop through those vals and only push if it dose not exist in the array.
var arr = [7,3,1];
function pushNew(obj) {
var prams = obj;
for(var k = 0; k < obj.length; k++){
for (var i = 0; i < arr.length; i++) {
if (arr[i] == prams[k]) {
return;
}
}
array.push(prams[k]);
}
// console.info(arr);
}
pushNew([2,7,4]);
A short and more modern way to just get all the unique values is to use Array.from with Set. A Set is an array-like structure that will only hold unique values. Array.from converts an array-like structure into a real array.
In your case, you can just concat both arrays, pass them to Set to remove the duplicates, and use Array.from to convert it back to a regular array.
var arr1 = [1, 2, 3, 4, 5];
var arr2 = [3, 4, 5, 6, 7];
var result = Array.from(new Set(arr1.concat(arr2)));
document.write(JSON.stringify(result));
Actually, your existing code nearly works.
You can set a flag if you find a match in the inner loop and instead of return you should use break to escape the loop. Then use push after the inner loop if a match wasn't found. Also, there is no need for both obj and prams (which I've renamed to params), so:
var arr = [7,3,1];
function pushNew(params) {
var found;
for(var k=0; k<params.length; k++){
// Set found to initial value on each outer loop
found = false;
for (var i=0; i<arr.length; i++) {
// If find match, set flag and break from loop (for efficiency)
if (arr[i] == params[k]) {
found = true;
break;
}
}
// If match not found, push into arr
if (!found) arr.push(params[k]);
}
}
pushNew([7,2])
document.write(arr); // 7,3,1,2
If you want efficient code, consider creating an index and using in:
var arr = [7,3,1];
function addParams(params) {
var index = arr.reduce(function(acc, v) {
acc[v] = true;
return acc;
},{});
params.forEach(function(v) {
if (!(v in index)) arr.push(v);
});
}
addParams([7,3,2]);
document.write(arr);
You can use indexOf to validate if element is present in an array. forEach is another array method which works like loop.
var arr = [7,3,1];
function pushNew(obj) {
//var prams = obj;
obj.forEach(function(item){ // iterate through each element
if(arr.indexOf(item) == -1){ //indexOf return -1 is element is not present in an array
arr.push(item)
}
})
console.log(arr);
}
pushNew([2,7,4]);
Working Jsfiddle
var arr = [7, 3, 1];
function pushNew(obj) {
for (var k = 0; k < obj.length; k++) {
if (arr.indexOf(obj[k]) == -1) {
arr.push(obj[k]);
}
}
}
pushNew([2, 7, 4]);
You can use _.union function of lodash.
_.union([2, 1], [4, 2], [1, 2]);
// → [2, 1, 4]
How can I remove an object from a copy of an array without removing it from the original?
I have a global variable :
var userTrickList = [];
And inside a function, I make a copy of that global array :
var tempUserTrickList = userTrickList;
Then I use the removeItem function that I created to remove a certain object.
removeItem(considerTrick.IDName, tempUserTrickList);
function removeItem(item, list) {
//takes a string as 'item', finds in the array as 'list',
//then removes it from the list.
for(var i = 0; i < list.length; i++)
{
if(item === list[i])
{
list.splice(i,1);
}
}
}
My problem is, this function removes it from the userTrickList too.
Any ideas? It's definitely a problem in "removeItem(considerTrick.IDName, tempUserTrickList);", but I can't think of a solution.
Use .slice(0) to clone an array.
var tempUserTrickList = userTrickList.slice(0);
Credits:
http://davidwalsh.name/javascript-clone-array
use this function for your requirement
function removeElementFromArray(data,target) {
var temp=new Array();
for ( var i = 0; i < data.length; i++) {
if(data[i]!=target){
temp.push(data[i]);
}
}
return temp; }
here data is original array and target is the element you want to remove from array
this function will return array without containing the removed item.
Try, It copy the original array
var tempUserTrickList = JSON.parse(JSON.stringify(userTrickList));
Demo CopyArray
for (i = 0, l = arr.length; i < l; i++) {
if (arr[i] === item) {
arr.splice(i, 1);
i -= 1;
l -= 1;
}
}
Daniel's method of cloning an array is absolutely correct, but since I don't see an ES6-oriented answer, I'll offer up an alternative solution:
We can just as easily use the spread operator to clone an array, so we don't have to use the slice call.
const arr = [1, 2, 3];
const copy = [...arr];
copy.pop();
console.log(arr); // returns [1, 2, 3]
console.log(copy); // returns [1, 2]
This question already has answers here:
In Javascript, how do I check if an array has duplicate values?
(9 answers)
Closed 10 months ago.
I wanted to write a javascript function which checks if array contains duplicate values or not.
I have written the following code but its giving answer as "true" always.
Can anybody please tell me what am I missing.
function checkIfArrayIsUnique(myArray)
{
for (var i = 0; i < myArray.length; i++)
{
for (var j = 0; j < myArray.length; j++)
{
if (i != j)
{
if (myArray[i] == myArray[j])
{
return true; // means there are duplicate values
}
}
}
}
return false; // means there are no duplicate values.
}
An easy solution, if you've got ES6, uses Set:
function checkIfArrayIsUnique(myArray) {
return myArray.length === new Set(myArray).size;
}
let uniqueArray = [1, 2, 3, 4, 5];
console.log(`${uniqueArray} is unique : ${checkIfArrayIsUnique(uniqueArray)}`);
let nonUniqueArray = [1, 1, 2, 3, 4, 5];
console.log(`${nonUniqueArray} is unique : ${checkIfArrayIsUnique(nonUniqueArray)}`);
let arr = [11,22,11,22];
let hasDuplicate = arr.some((val, i) => arr.indexOf(val) !== i);
// hasDuplicate = true
True -> array has duplicates
False -> uniqe array
This should work with only one loop:
function checkIfArrayIsUnique(arr) {
var map = {}, i, size;
for (i = 0, size = arr.length; i < size; i++){
if (map[arr[i]]){
return false;
}
map[arr[i]] = true;
}
return true;
}
You got the return values the wrong way round:
As soon as you find two values that are equal, you can conclude that the array is not unique and return false.
At the very end, after you've checked all the pairs, you can return true.
If you do this a lot, and the arrays are large, you might want to investigate the possibility of sorting the array and then only comparing adjacent elements. This will have better asymptotic complexity than your current method.
Assuming you're targeting browsers that aren't IE8,
this would work as well:
function checkIfArrayIsUnique(myArray)
{
for (var i = 0; i < myArray.length; i++)
{
if (myArray.indexOf(myArray[i]) !== myArray.lastIndexOf(myArray[i])) {
return false;
}
}
return true; // this means not unique
}
Here's an O(n) solution:
function hasDupes(arr) {
/* temporary object */
var uniqOb = {};
/* create object attribute with name=value in array, this will not keep dupes*/
for (var i in arr)
uniqOb[arr[i]] = "";
/* if object's attributes match array, then no dupes! */
if (arr.length == Object.keys(uniqOb).length)
alert('NO dupes');
else
alert('HAS dupes');
}
var arr = ["1/1/2016", "1/1/2016", "2/1/2016"];
hasDupes(arr);
https://jsfiddle.net/7kkgy1j3/
Another solution:
Array.prototype.checkIfArrayIsUnique = function() {
this.sort();
for ( var i = 1; i < this.length; i++ ){
if(this[i-1] == this[i])
return false;
}
return true;
}
function hasNoDuplicates(arr) {
return arr.every(num => arr.indexOf(num) === arr.lastIndexOf(num));
}
hasNoDuplicates accepts an array and returns true if there are no duplicate values. If there are any duplicates, the function returns false.
Without a for loop, only using Map().
You can also return the duplicates.
(function(a){
let map = new Map();
a.forEach(e => {
if(map.has(e)) {
let count = map.get(e);
console.log(count)
map.set(e, count + 1);
} else {
map.set(e, 1);
}
});
let hasDup = false;
let dups = [];
map.forEach((value, key) => {
if(value > 1) {
hasDup = true;
dups.push(key);
}
});
console.log(dups);
return hasDup;
})([2,4,6,2,1,4]);
Late answer but can be helpful
function areThereDuplicates(args) {
let count = {};
for(let i = 0; i < args.length; i++){
count[args[i]] = 1 + (count[args[i]] || 0);
}
let found = Object.keys(count).filter(function(key) {
return count[key] > 1;
});
return found.length ? true : false;
}
areThereDuplicates([1,2,5]);
The code given in the question can be better written as follows
function checkIfArrayIsUnique(myArray)
{
for (var i = 0; i < myArray.length; i++)
{
for (var j = i+1; j < myArray.length; j++)
{
if (myArray[i] == myArray[j])
{
return true; // means there are duplicate values
}
}
}
return false; // means there are no duplicate values.
}
Returns the duplicate item in array and creates a new array with no duplicates:
var a = ["hello", "hi", "hi", "juice", "juice", "test"];
var b = ["ding", "dong", "hi", "juice", "juice", "test"];
var c = a.concat(b);
var dupClearArr = [];
function dupArray(arr) {
for (i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) != i && arr.indexOf(arr[i]) != -1) {
console.log('duplicate item ' + arr[i]);
} else {
dupClearArr.push(arr[i])
}
}
console.log('actual array \n' + arr + ' \nno duplicate items array \n' + dupClearArr)
}
dupArray(c);
const containsMatches = (a1, a2) => a1.some((v) => a2.includes(v));
If your array nests other arrays/objects, using the Set approach may not be what you want since comparing two objects compares their references. If you want to check that their contained values are equal, something else is needed. Here are a couple different approaches.
Approach 1: Map using JSON.stringify for keys
If you want to consider objects with the same contained values as equal, here's one simple way to do it using a Map object. It uses JSON.stringify to make a unique id for each element in the array.
I believe the runtime of this would be O(n * m) on arrays, assuming JSON.stringify serializes in linear time. n is the length of the outer array, m is size of the arrays. If the objects get very large, however, this may slow down since the keys will be very long. Not a very space-efficient implementation, but it is simple and works for many data types.
function checkArrayDupeFree(myArray, idFunc) {
const dupeMap = new Map();
for (const el of myArray) {
const id = idFunc(el);
if (dupeMap.has(id))
return false;
dupeMap.set(id, el);
}
return true;
}
const notUnique = [ [1, 2], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(notUnique)} has no duplicates? ${checkArrayDupeFree(notUnique, JSON.stringify)}`);
const unique = [ [2, 1], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(unique)} has no duplicates? ${checkArrayDupeFree(unique, JSON.stringify)}`);
Of course, you could also write your own id-generator function, though I'm not sure you can do much better than JSON.stringify.
Approach 2: Custom HashMap, Hashcode, and Equality implementations
If you have a lot of big arrays, it may be better performance-wise to implement your own hash/equality functions and use a Map as a HashMap.
In the following implementation, we hash the array. If there is a collision, map a key to an array of collided values, and check to see if any of the array values match according to the equality function.
The downside of this approach is that you may have to consider a wide range of types for which to make hashcode/equality functions, depending on what's in the array.
function checkArrayDupeFreeWHashes(myArray, hashFunc, eqFunc) {
const hashMap = new Map();
for (const el of myArray) {
const hash = hashFunc(el);
const hit = hashMap.get(hash);
if (hit == null)
hashMap.set(hash, [el]);
else if (hit.some(v => eqFunc(v, el)))
return false;
else
hit.push(el);
}
return true;
}
Here's a demo of the custom HashMap in action. I implemented a hashing function and an equality function for arrays of arrays.
function checkArrayDupeFreeWHashes(myArray, hashFunc, eqFunc) {
const hashMap = new Map();
for (const el of myArray) {
const hash = hashFunc(el);
const hit = hashMap.get(hash);
if (hit == null)
hashMap.set(hash, [el]);
else if (hit.some(v => eqFunc(v, el)))
return false;
else
hit.push(el);
}
return true;
}
function arrayHasher(arr) {
let hash = 19;
for (let i = 0; i < arr.length; i++) {
const el = arr[i];
const toHash = Array.isArray(el)
? arrayHasher(el)
: el * 23;
hash = hash * 31 + toHash;
}
return hash;
}
function arrayEq(a, b) {
if (a.length != b.length)
return false;
for (let i = 0; i < a.length; i++) {
if ((Array.isArray(a) || Array.isArray(b)) && !arrayEq(a[i], b[i]))
return false;
else if (a[i] !== b[i])
return false;
}
return true;
}
const notUnique = [ [1, 2], [1, 3], [1, 2] ];
const unique = [ [2, 1], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(notUnique)} has no duplicates? ${checkArrayDupeFreeWHashes(notUnique, arrayHasher, arrayEq)}`);
console.log(`${JSON.stringify(unique)} has no duplicates? ${checkArrayDupeFreeWHashes(unique, arrayHasher, arrayEq)}`);
function checkIfArrayIsUnique(myArray)
{
isUnique=true
for (var i = 0; i < myArray.length; i++)
{
for (var j = 0; j < myArray.length; j++)
{
if (i != j)
{
if (myArray[i] == myArray[j])
{
isUnique=false
}
}
}
}
return isUnique;
}
This assume that the array is unique at the start.
If find two equals values, then change to false
i think this is the simple way
$(document).ready(function() {
var arr = [1,2,3,9,6,5,6];
console.log( "result =>"+ if_duplicate_value (arr));
});
function if_duplicate_value (arr){
for(i=0;i<arr.length-1;i++){
for(j=i+1;j<arr.length;j++){
if(arr[i]==arr[j]){
return true;
}
}
}
return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var c=[2,2,3,3,5,5,4,4,8,8];
for(var i=0; i<b.length; i++){
for(var j=i+1; j<b.length; j++){
if(c[i]==c[j]){
console.log(c[j]);
}
}
}
var arr = [4, 5, 7, 8, 14, 45, 76];
function even(a) {
var ar = [];
for (var i = 0; i < a.length; i++) {
ar.push(a[2 * i + 1]);
}
return ar;
}
alert(even(arr));
http://jsbin.com/unocar/2/edit
I have tried this code in order to output even (index) elements of an array. It works, but it also outputs some empty elements. How do I fix this code to output only existing elements?
Either use modulus:
for (var i = 0; i < a.length; i++) {
if(i % 2 === 0) { // index is even
ar.push(a[i]);
}
}
or skip every second element by incrementing i accordingly:
for(var i = 0; i < a.length; i += 2) { // take every second element
ar.push(a[i]);
}
Notice: Your code actually takes the elements with odd indexes from the array. If this is what you want you have to use i % 2 === 1 or start the loop with var i = 1 respectively.
For IE9+ use Array.filter
var arr = [4,5,7,8,14,45,76];
var filtered = arr.filter(function(element, index, array) {
return (index % 2 === 0);
});
With a fallback for older IEs, all the other browsers are OK without this fallback
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
This will work on 2018 :)
take the odd indexes and apply to filter
var arr = [4, 5, 7, 8, 14, 45, 76, 5];
let filtered = arr.filter((a,i) => i%2===1);
console.log(filtered);
Even if this question is quite old, I would like to add a one-liner filter:Odd numbers: arr.filter((e,i)=>i%2)Even numbers: arr.filter((e,i)=>i%2-1)A more 'legal' way for even numbers: arr.filter((e,i)=>!(i%2))
There's no need to check with ===1 like sumit said. mod 2 already returns a 0 or a 1, you can let them be interpreted as boolean values.
You can use i&1 instead of i%2, while it benefits performance on big arrays, it can work only on 31 bit integers.
why don't you try with the % operator. It gives you the remaining of a division.
replace the loop block with
if ((i % 2) === 0) {
ar.push(a[i])
}
var arr = [4,5,7,8,14,45,76];
function even(a)
{
var ar = [];
for (x in a)
{
if((a[x]%2)==0)
ar.push(a[x]);
}
return ar;
}
alert(even(arr));
I just wanted to explain why your result is not what you expected since everyone else shows excellent solutions. You are iterating over an array size N so your resulting array will attempt to push elements in an array that will result in size N. Since only N/2 will be found in the original array your resulting array will fill the rest with blanks to fill in the rest of N. So if you checked to see if a[2*i] exists OR checked to see if a[i] % 2 == 0 before inserting, your resulting array will contain only the even indexed values
You need to test the elements for evenness like this:
var arr = [4,5,7,8,14,45,76];
function even(a){
var ar = [];
for (var i=0; i<a.length;i++){
if (a[i] % 2 === 0)
{
ar.push(a[i]);
}
}
return ar;
}
alert(even(arr));
%2 is the modulo operator, it returns the remainder of integer division.