Javascript Nested Array Return Even Numbers - javascript

I am trying to write a function that prints only the even numbers from a nested array. Here is my attempt and it keeps returning "undefined".
function printEvents(){
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
for (var i = 0; i<nestedArr.length; i++) {
for (var j = 0; j<nestedArr[i]; j++) {
var evenNumbers = nestedArr[i][j]
}
}
if (evenNumbers % 2 == 0) {
console.log(evenNumbers)
}
}
printEvents();

You could use a recursive approach, if the item is an array. You need to move the test for evenness inside of the for loop.
function printEvents(array) {
var i;
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
printEvents(array[i]);
continue;
}
if (array[i] % 2 == 0) {
console.log(array[i]);
}
}
}
printEvents([[1, 2, 3], [4, 5, 6], [7, 8], [9, 10, 11, 12], [[[13, [14]]]]]);
Solution with a callback
function getEven(a) {
if (Array.isArray(a)) {
a.forEach(getEven);
return;
}
if (a % 2 == 0) {
console.log(a);
}
}
getEven([[1, 2, 3], [4, 5, 6], [7, 8], [9, 10, 11, 12], [[[13, [14]]]]]);

You just have a couple issues. You need to check the length of your nested arrays and you need to move your code that checks whether a number is even or not inside the array.
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
for (var i = 0; i<nestedArr.length; i++) {
for (var j = 0; j<nestedArr[i].length; j++) {
var evenNumbers = nestedArr[i][j]
if (evenNumbers % 2 == 0) {
console.log(evenNumbers)
}
}
}

You can do this more easy using filter method which accepts a callback method.
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
var mergedArray=[].concat.apply([], nestedArr);
console.log(mergedArray.filter(a => a%2 == 0));

You can use reduce with every for something quick.
var nestedArr = [ [1, 2, 3],[4, 5, 6],[7, 8],[9, 10, 11, 12]];
var sift = nestedArr.reduce(function(r,o) {
o.every(i => i % 2 === 0 ? r.push(i) : true)
return r;
}, []);
console.log(sift);
If you want a one-liner you can use ReduceRight with Filter
var nestedArr = [[1, 2, 3],[4, 5, 6],[7, 8],[9, 10, 11, 12]];
var sift = nestedArr.reduceRight((p, b) => p.concat(b).filter(x => x % 2 === 0), []);
console.log(sift)

Related

Algorithm problem with array subsequences [duplicate]

I am trying to write a function that will take an array and n as parameters,
it will return all subsets of that array with n elements, have tried a couple things, couldn't yet succeed.
thanks to whoever put it here, this functions is way too complicated and doesn't do the job, basically what I tried to do here is to pick out one element from a 4 element array to create its 3 element subsets. It doesn't even take N as parameter. it returns all 3 element subsets but also identical ones, so I have to filter them out as well, in any case I will keep trying.
function findSubsets(array) {
var answers = [];
var firstArray = array;
for (i = 0; i < array.length; i++) {
array = firstArray;
for (var k = 0; k < array.length; k++) {
if (k != i) {
var subset = array.splice(k, 1);
answers.push(array); array.splice(k, 0, subset[0]);
}
}
}
}
That not as complicated as it seems. This one is optimized because it doesn't creates useless temporary arrays during the process.
function findSubsets(array, n) {
var answers = [];
for(var i = 0 ; i < array.length ; i += n) {
answers.push(array.slice(i, i + n));
}
return answers;
}
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) // --> [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) // --> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
You can try this solution
var subsetArray = (function() {
return {
getResult: getResult
}
function getResult(array, n) {
function isBigEnough(value) {
return value.length === n;
}
var ps = [
[]
];
for (var i = 0; i < array.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(array[i]));
}
}
return ps.filter(isBigEnough);
}
})();
var arr = [1, 2, 3, 4,5,6,7,8,9];
console.log(subsetArray.getResult(arr,2));

Find smallest common number in all arrays

The task:
You are given 3 sorted arrays. You should find the smallest number
that is common in all 3 arrays and return it. If such a number doesn't
exist, return -1
My approach:
Use early exit: If one of the array is empty, then we know there won't be a common number in all arrays
Create pointer that points to the first element of the corresponding array
In the outer loop, loop through all elements of the first array. If any of the pointer over reaches the end of the array, then break the loop because we have reached the end and haven't found a common number
In the first inner loop check the second array for the element the pointer of the first array is pointing to
If you found it then set a flag. Otherwise remember the running index to the second pointer so we can continue at this element in the next iteration
If the flag is set, then loop through the second inner loop. In here it's analogous to the first inner loop: Search for the current element in the 3rd array.
If you find it, then immediately return the value. If not go to the next element until you find an element bigger than the current one
Increment the pointer of the first array
Do this until you reach either one of the array
My Solution:
let findLeastCommonNumber = function(a, b, c) {
if (a.length === 0 || b.length === 0 || c.length === 0) {
return -1;
}
let aPointer = 0;
let bPointer = 0;
let cPointer = 0;
while (aPointer < a.length ||
bPointer < b.length ||
cPointer < c.length) {
const aValue = a[aPointer];
let bFound = false;
for (let i = bPointer; i < b.length; i++) {
if (b[i] === aValue) {
bPointer = i;
bFound = true;
break;
}
if (b[i] > aValue) {
bPointer = i;
break;
}
}
if (bFound) {
for (let i = cPointer; i < c.length; i++) {
if (c[i] === aValue) {
return a[aPointer];
}
if (c[i] > aValue) {
cPointer = i;
break;
}
}
}
aPointer++;
}
return -1;
};
Sample solution:
let find_least_common_number = function(a, b, c) {
let i = 0;
let j = 0;
let k = 0;
while (i < a.length
&& j < b.length
&& k < c.length) {
// Finding the smallest common number
if (a[i] === b[j]
&& b[j] === c[k]) {
return a[i];
}
// Let's increment the iterator
// for the smallest value.
if (a[i] <= b[j]
&& a[i] <= c[k]) {
i++;
} else if (b[j] <= a[i]
&& b[j] <= c[k]) {
j++;
} else if (c[k] <= a[i]
&& c[k] <= b[j]) {
k++;
}
}
return -1;
};
I like the fact that the sample solution has less nesting. But the sample solution doesn't take advantage of an early exit and I think my solution is more scalable. Let's say the requirements changes, and 27 arrays more are now included. In my solution, I'd just copy the inner loops and change the pointer names only. I don't need to touch existing code. In the sample solution, however, I'd have touch every line of code that refers to one of the arrays and I would add the new arrays there. What do you think?
You could a completely dynamic approach for an infinite (sort of) count of arrays.
function findLeastCommonNumber(...array) {
var indices = array.map(_ => 0),
smallest = Math.max(...array.map((a, i) => a[indices[i]])),
next;
while (indices.every((i, j) => i < array[j].length)) {
next = smallest;
array.forEach((a, i) => {
while (indices[i] < a.length && a[indices[i]] < smallest)
next = Math.max(next, a[++indices[i]]);
});
if (array.every((a, i) => a[indices[i]] === smallest)) return smallest;
smallest = next;
}
return -1;
}
console.log(findLeastCommonNumber([1, 2, 3, 4, 5, 7], [8, 9, 10], [1, 2, 3, 5, 6, 7, 9]));
console.log(findLeastCommonNumber([1, 2, 3, 4, 5, 7, 9, 10], [1, 2, 3, 5, 6, 7, 9, 10], [4, 6, 7, 8, 9, 10, 11, 12]));
console.log(findLeastCommonNumber([1, 5, 6, 7, 8, 10], [5, 6, 9, 10], [1, 2, 3, 4, 5, 6, 9, 10]));
For the more readable solution, you can use this:
const findLeastCommonNumber = function() {
const total = [].concat(...arguments).sort((a,b) => a > b ? 1 : -1);
let index = 0;
let commonNumber = -1;
while(total.length - 2 > index && commonNumber === -1){
if(total[index] === total[index + 1] && total[index] === total[index + 2]){
commonNumber = total[index];
}
index++;
}
return commonNumber;
};
console.log(findLeastCommonNumber([1,5,6,7,8,10],[5,6,9,10],[1,2,3,4,5,6,9,10]));
An alternative solution - Take the 1st array, and convert the other arrays to Sets. Now use Array.find() on the 1st array, and check with Array.every() if the current number is found in all sets.
const findLeastCommonNumber = (main, ...array) => {
const sets = array.map(o => new Set(o));
const common = main.find(n => sets.every(s => s.has(n)));
return common === undefined ? -1 : common;
};
console.log(findLeastCommonNumber([1, 2, 3, 4, 5, 7], [8, 9, 10], [1, 2, 3, 5, 6, 7, 9]));
console.log(findLeastCommonNumber([1, 2, 3, 4, 5, 7, 9, 10], [1, 2, 3, 5, 6, 7, 9, 10], [4, 6, 7, 8, 9, 10, 11, 12]));
console.log(findLeastCommonNumber([1, 5, 6, 7, 8, 10], [5, 6, 9, 10], [1, 2, 3, 4, 5, 6, 9, 10]));
The arrays are sorted in ascending order. We will use three
iterators simultaneously to traverse each of the arrays. We can
start traversing each array from the 0^{th}index, which always has
the smallest value.
If the values pointed to by the three iterators are equal, that is
the solution. Since the arrays are sorted in ascending order, that
value must be the smallest value present in all of the arrays.
Otherwise, we see which of the three iterators points to the
smallest value and increment that iterator so that it points to the
next index.
If any of the three iterators reaches the end of the array before
we find the common number, we return -1.
let findLeastCommonNumber = function(arr1, arr2, arr3) {
// Initialize starting indexes for arr1, arr2 and arr3
let i = 0;
let j = 0;
let k = 0;
// Iterate through three arrays
while (i < arr1.length && j < arr2.length && k < arr3.length) {
// Finding the smallest common number
if (arr1[i] === arr2[j] && arr2[j] === arr3[k]) {
return arr1[i];
}
// Let's increment the iterator
// for the smallest value.
if (arr1[i] <= arr2[j] && arr1[i] <= arr3[k]) {
i++;
}
else if (arr2[j] <= arr1[i] && arr2[j] <= arr3[k]) {
j++;
}
else if (arr3[k] <= arr1[i] && arr3[k] <= arr2[j]) {
k++;
}
}
return -1;
};
let v1 = [6, 7, 10, 25, 30, 63, 64];
let v2 = [0, 4, 5, 6, 7, 8, 50];
let v3 = [1, 6, 10, 14];
console.log("Least Common Number: " + findLeastCommonNumber(v1, v2, v3));

Union between three arrays

I need to find the union of three arrays that get passed to the function union.
It took me about 50lines to code to get the expected result. Apparently, the following code works but now I wonder what are the best ways (either in a functional and in a non-functional fashion) to do the same job.
function union(...arrays) {
var array1 = arguments[0];
var array2 = arguments[1];
var array3 = arguments[2];
var unique = [];
var intersaction = [];
// find the unique values
for(let i = 0; i < array1.length; i++) {
if( (array2.includes(array1[i]) == false) && (array3.includes(array1[i])) == false ) {
unique.push(array1[i]);
}
}
for(let i = 0; i < array2.length; i++) {
if( (array1.includes(array2[i]) == false) && (array3.includes(array2[i])) == false ) {
unique.push(array2[i]);
}
}
for(let i = 0; i < array3.length; i++) {
if( (array1.includes(array3[i]) == false) && (array2.includes(array3[i])) == false ) {
unique.push(array3[i]);
}
}
// find the intersection
for(let j = 0; j < array1.length; j++) {
if(array2.includes(array1[j]) || array3.includes(array1[j]) ) {
if (intersaction.indexOf(array1[j]) == -1) {
intersaction.push(array1[j]);
}
}
}
for(let j = 0; j < array2.length; j++) {
if(array1.includes(array2[j]) || array3.includes(array2[j]) ) {
if (intersaction.indexOf(array2[j]) == -1) {
intersaction.push(array2[j]);
}
}
}
for(let j = 0; j < array3.length; j++) {
if(array1.includes(array3[j]) || array2.includes(array3[j]) ) {
if (intersaction.indexOf(array3[j]) == -1) {
intersaction.push(array3[j]);
}
}
}
return union = [...intersaction, ...unique];
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
// should log: [5, 10, 15, 88, 1, 7, 100]
Just another solution keeping the original function signature provided by the OP:
function union(...arrays) {
return Array.from(new Set([...arrays].flat()));
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
Or, even shorter (but less read friendly):
return [...(new Set([...arrays].flat()))];
Explanation:
Array.from takes an Iterable as an argument, this will create a new array from the original one.
[...arrays] spreads the arrays (argument) into a new, single, one (So it becomes an array of arrays) -> [5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5] becomes: [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]]
.flat flattens the array, making that an array of values rather than ar array of arrays of values -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat -> [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]] becomes [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5]
new Set removes duplicates from the array and returns an Iterable https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set. -> [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5] becomes a Set instance (an Iterable) without the duplicates. Array.from then converts the Set (Iterable) to a regular array. Further infos here: How to convert Set to Array?
BEWARE: Array.flat is currently an experimental feature (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat). Solution without using flat below:
function union(...arrays) {
return Array.from(new Set([].concat.apply([],[...arrays])));
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
Explanation (only differences from above):
Instead of .flat, we apply to Array.concat our original array, so that it will flatten it passing a new array as its this and providing our array as the argument: [].concat.apply([],[...arrays])
Snippet: http://jsfiddle.net/briosheje/y03osape/2/
Snippet without .flat: http://jsfiddle.net/briosheje/y03osape/4/
use set that's very simple,
The Set object lets you store unique values of any type, whether
primitive values or object
var a= [5, 10, 15];
var b=[15, 88, 1, 5, 7];
var c=[100, 15, 10, 1, 5];
var result= [...new Set([...a, ...b,...c])];
console.log(result);
I tried to copy your approach of looping over arrays but in a slightly more efficient manner, using only ES5 safe functions. I'm sure the other answers are more efficient if you can use the features they do.
var a = [1, 2, 3];
var b = [1, 2, 4, 5];
var c = [2, 7, 9];
// takes an array of arrays
function getUnique(input) {
var unique = [];
// loop over each array
input.forEach(function(item) {
// loop over each value
item.forEach(function(value) {
// if it's not already in the unique array,
if (unique.indexOf(value) == -1) {
// add it
unique.push(value);
}
});
});
return unique;
}
// takes an array of arrays
function getIntersection(input) {
// assume all elements in first array are common
var intersection = input.shift();
var remove = [];
// loop over items in first array and attempt to
// disprove commonality
intersection.forEach(function(value) {
// loop over subsequent arrays
for (var i = 0; i < input.length; i++) {
var item = input[i];
// if these arrays don't contain the value,
// then it isn't an intersection
if (item.indexOf(value) == -1) {
// add it to an array to be removed
remove.push(value);
// exit this loop
break;
}
}
});
// remove values determined not to be intersections
remove.forEach(function(value) {
intersection.splice(intersection.indexOf(value), 1);
})
return intersection;
}
var test = getUnique([a, b, c]);
console.log(test);
var test2 = getIntersection([a, b, c]);
console.log(test2);
Based on custom forEach and Reduce from previously in the exercise at http://csbin.io/callbacks
function forEach(array, callback) {
for(i = 0; i < array.length; i++){
callback(array[i])
}
}
function reduce(array, callback, initialValue) {
for(let i of array){
initialValue = callback(initialValue, i)
}
return initialValue
}
function union(...arrays) {
return reduce(arrays, (seen, next) => {
forEach(next, (element) => {
if(!seen.includes(element)) seen.push(element);
})
return seen
}, [])
}
Note if you use the in-built reduce function you can remove the empty inital array requirement.

Looping through two (different lengthed) arrays to produce an alternating output

What is an efficient way of looping through two arrays to produce an alternating output? In JavaScript.
If I have two arrays like this:
var oddNumbers = [1, 3, 5, 7, 9]
var evenNumbers = [2, 4, 6, 8, 10, 12, 14]
NB: The arrays may not be the same length
How can I get the following output?
Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14
I would have thought this would work:
if (oddNumber.length > evenNumbers.length) {
var large = oddNumbers;
} else {
var large = evenNumbers;
}
for(var i = 0; i < large.length; i++){
if (evenNumbers.length >= i && oddNumbers.length >= i) {
console.log(oddNumbers[i] + ", " + evenNumbers[0]);
} elseif (evenNumbers.length >= i) {
console.log(evenNumbers[0]);
} else {
console.log(oddNumbers[0]);
}
}
But it's pretty messy, any better way of approaching this?
NOTE: These may not necessarily be in a numerical order, or in fact numbers
I would rather do it as follows if you just want to output them:
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
for (var i=0, j=0; i < oddNumbers.length || j < evenNumbers.length;) {
if (i < oddNumbers.length) {
console.log(oddNumbers[i++]);
}
if (j < evenNumbers.length) {
console.log(evenNumbers[j++]);
}
}
If you want to get the merge result as another array you can replace console.log with result.push to push result values on an array named result as follows:
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var result = [];
for (var i=0, j=0; i < oddNumbers.length || j < evenNumbers.length;) {
if (i < oddNumbers.length) {
result.push(oddNumbers[i++]);
}
if (j < evenNumbers.length) {
result.push(evenNumbers[j++]);
}
}
console.log(result);
This way you iterate both arrays as long as one of them has an element that we haven't visited yet and also prevents iterating over the same index of same array twice. Please note that I used increment in if blocks to save 2 lines of code. You can also move them to the for loop since they won't break if statements.
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var oLength = oddNumbers.length;
var eLength = evenNumbers.length;
var n = oLength > eLength ? oLength : eLength;
var rez=[];
for(i=0;i<n;i++){
if (i< oLength) rez.push(oddNumbers[i])
if (i<eLength) rez.push(evenNumbers[i])
}
console.log(rez);
var odd = ["A", "C","E","G"];
var even = ["B","D","F"];
var rez=[];
for(i=0;i<(odd.length > even.length ? odd.length : even.length);i++){
if (i< odd.length) rez.push(odd[i])
if (i<even.length) rez.push(even[i])
}
console.log(rez);
The following function accepts two arrays and returns their interleaved values as a new array:
function interleaveArrays(a, b) {
var array = [],
limit = a.length >= b.length ? a.length : b.length;
index = 0;
while (index < limit) {
a[index] && array.push(a[index]);
b[index] && array.push(b[index]);
index += 1;
}
return array;
}
Calling the function like so:
var oddNumbers = [1, 3, 5, 7, 9],
evenNumbers = [2, 4, 6, 8, 10, 12, 14];
console.log(interleaveArrays(oddNumbers, evenNumbers));
Yields:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14 ]
You can then output this in your preferred manner; e.g:
var interleaved = interleaveArrays(oddNumbers, evenNumbers);
// as a loop
interleaved.forEach(function (n) {
console.log(n);
})
// or as a string
console.log(interleaved.join(', '));
// etc.
Hope this helps :)
I'd do something like this.
large = (oddNumber.length >= evenNumbers.length) ? oddNumbers : evenNumbers;
small = (oddNumber.length < evenNumbers.length) ? oddNumbers : evenNumbers;
for(var i = 0; i < large.length; i++){
if(small.length <= i + 1){
console.log(small[i] + ", "+ large[i]);
}
else {
console.log(large[i]);
}
}
A long-hand example of how it can be done. The code can be shrunk for a final solution. The basic principle I'm using is to even out the lengths to take care of the alternating then tag on the tail
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var oLength = oddNumbers.length;
var eLength = evenNumbers.length;
var oTemp, eTemp, remainder;
if(oLength > eLength) {
eTemp = evenNumbers;
oTemp = oddNumbers.slice(0, eLength);
remainder = oddNumbers.slice(eLength);
} else if (eLength > oLength) {
eTemp = evenNumbers.slice(0, oLength);
oTemp = oddNumbers;
remainder = evenNumbers.slice(oLength);
} else {
eTemp = evenNumbers;
oTemp = oddNumbers;
remainder = [];
}
var final = [];
for(var i=0; i < eTemp.length; i++) {
final.push(oTemp[i]);
final.push(eTemp[i]);
}
final = final.concat(remainder);
alert(final);
I would simply merge the two array and sort it
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var mergedArr=oddNumbers.concat(evenNumbers );
console.log(mergedArr.sort(function(a,b){return a-b;}));
See No loop.. No hassle. Very Simple
There will be an extra , on the screen. Add an if statement if you don't want that
for(var i = 0; i < large.length; i++){
if(i<evenNumbers.length)
console.log(evenNumbers[i]+",");
if(i<oddNumber.length)
console.log(evenNumbers[i]+",");
}
try this it will work always either number Array or String Array:
var oddNumber = [1, 3, 5, 7, 9]
var evenNumber = [2, 4, 6, 8, 10, 12, 14]
var margedNumbers = oddNumber.concat(evenNumber);
console.log("before: "+margedNumbers);
margedNumbers.sort(function(a, b){return a-b})
console.log("after: "+margedNumbers)
My solution
var oddNumbers = [1, 3, 5, 7, 9]
var evenNumbers = [2, 4, 6, 8, 10, 12, 14]
var extraElements = (oddNumbers.length > evenNumbers.length) ? oddNumbers.slice(evenNumbers.length) : evenNumbers.slice(oddNumbers.length);
var finalArr = [];
var small = (oddNumbers.length < evenNumbers.length) ? oddNumbers : evenNumbers;
small.forEach((each, index) => {
// merge elements in desired order
finalArr.push(oddNumbers[index]);
finalArr.push(evenNumbers[index]);
})
finalArr = finalArr.concat(extraElements);
alert(finalArr);
Extract the extra elements which makes both array of same length. Then, in a simple iteration, push elements from both array with same index.

Deleting both values from array if duplicate - JavaScript/jQuery

I have an array here:
var myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
Now I want to remove both appearances of a duplicate. So the desired result is not:
var myArr = [1, 2, 5, 7, 8 ,9];
but
var myArr = [2, 7, 8];
Basically I know how to remove duplicates, but not in that that special way. Thats why any help would be really appreciated!
Please note: My array is filled with strings. The numbers here were only used as an example.
jsfiddle for this code:
var myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
var newArr = myArr;
var h,i,j;
for(h = 0; h < myArr.length; h++) {
var curItem = myArr[h];
var foundCount = 0;
// search array for item
for(i = 0; i < myArr.length; i++) {
if (myArr[i] == myArr[h])
foundCount++;
}
if(foundCount > 1) {
// remove repeated item from new array
for(j = 0; j < newArr.length; j++) {
if(newArr[j] == curItem) {
newArr.splice(j, 1);
j--;
}
}
}
}
Here's my version
var a = [1, 1, 2, 5, 5, 7, 8, 9, 9];
function removeIfduplicate( arr ) {
var discarded = [];
var good = [];
var test;
while( test = arr.pop() ) {
if( arr.indexOf( test ) > -1 ) {
discarded.push( test );
continue;
} else if( discarded.indexOf( test ) == -1 ) {
good.push( test );
}
}
return good.reverse();
}
x = removeIfduplicate( a );
console.log( x ); //[2, 7, 8]
EDITED with better answer:
var myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
function removeDuplicates(arr) {
var i, tmp;
for(i=0; i<arr.length; i++) {
tmp = arr.lastIndexOf(arr[i]);
if(tmp === i) {
//Only one of this number
} else {
//More than one
arr.splice(tmp, 1);
arr.splice(i, 1);
}
}
}
Using Hashmap
create hashmap and count occurencies
filter where hashmap.get(value) === 1 (only unique values)
const myArray = [1, 1, 2, 5, 5, 7, 8, 9, 9];
const map = new Map();
myArray.forEach(v => map.set(v, map.has(v) ? map.get(v)+1 : 1));
myArray.filter(v => map.get(v) === 1);
Old version (slower but valid too)
Heres a short version using Array.filter(). The trick is to first find all values that are NOT uniqe, and then use this array to reject all unique items in the original array.
let myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
let duplicateValues = myArr.filter((item, indx, s) => s.indexOf(item) !== indx);
myArr.filter(item => !duplicateValues.includes(item));
// => [2, 7, 8]
Wherever removing duplicates is involved, it's not a bad idea to use a set data structure.
JavaScript doesn't have a native set implementation, but the keys of an object work just as well - and in this case help because then the values can be used to keep track of how often an item appeared in the array:
function removeDuplicates(arr) {
var counts = arr.reduce(function(counts, item) {
counts[item] = (counts[item] || 0) + 1;
return counts;
}, {});
return Object.keys(counts).reduce(function(arr, item) {
if (counts[item] === 1) {
arr.push(item);
}
return arr;
}, []);
}
var myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
console.log(removeDuplicates(myArr), myArr);
Check out the example on jsfiddle.
Alternately, you could not use calls to reduce(), and instead use for and for(item in counts) loops:
function removeDuplicates(arr) {
var counts = {};
for(var i=0; i<arr.length; i++) {
var item = arr[i];
counts[item] = (counts[item]||0)+1;
}
var arr = [];
for(item in counts) {
if(counts[item] === 1) {
arr.push(item);
}
}
return arr;
}
Check out the example on jsfiddle.
If it's just alphanumeric, duplicates are case-sensitive, and there can be no more than two of any element, then something like this can work:
var a = [2, 1, "a", 3, 2, "A", "b", 5, 6, 6, "B", "a"],
clean_array = $.map(a.sort(), function (v,i) {
a[i] === a[i+1] && (a[i] = a[i+1] = null);
return a[i];
});
// clean_array = [1,3,5,"A","B","b"]
In this example,we are taking two arrays as function arguments, from this we are going to print only unique values of both arrays hence deleting the values that are present in both arrays.
first i am concatenating both the arrays into one. Then I taking each array value at a time and looping over the array itself searching for its no of occurrence. if no of occurrence(i.e.,count) equal to 1 then we are pushing that element into the result array. Then we can return the result array.
function diffArray(arr1, arr2) {
var newArr = [];
var myArr=arr1.concat(arr2);
var count=0;
for(i=0;i<myArr.length;i++){
for(j=0;j<myArr.length;j++){
if(myArr[j]==myArr[i]){
count++;
}
}
if(count==1){
newArr.push(myArr[i]);
}
count=0;
}
return newArr;
}
EDIT: Here is the jspref http://jsperf.com/deleting-both-values-from-array
http://jsfiddle.net/3u7FK/1/
This is the fastest way to do it in two passes without using any fancy tricks and keeping it flexible. You first spin through and find the count of every occurance and put it into and keyvalue pair. Then spin through it again and filter out the ones where the count was greater than 1. This also has the advanatage of being able to apply other filters than just "greater than 1"; as well as the having the count of occurances if you needed that as well for something else.
This should work with strings as well instead of numbers.
http://jsfiddle.net/mvBY4/1/
var myArr = [1, 1, 2, 5, 5, 7, 8, 9, 9];
var map = new Object();
for(var i = 0; i < myArr.length; i++)
{
if(map[myArr[i]] === undefined)
{
map[myArr[i]] = 1;
}
else
{
map[myArr[i]]++;
}
}
var result = new Array();
for(var i = 0; i < myArr.length; i++)
{
if(map[myArr[i]] > 1)
{
//do nothing
}
else
{
result.push(myArr[i]);
}
}
alert(result);
You can use Set (available in IE 11+) as below
const sourceArray = [1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8];
const duplicatesRemoved = new Set();
sourceArray.forEach(element => {
if (duplicatesRemoved.has(element)) {
duplicatesRemoved.delete(element)
} else {
duplicatesRemoved.add(element)
}
})
console.log(Array.from(duplicatesRemoved))
N.B. Arrow functions are not supported in older browsers. Use normal function syntax for that instead. However, Array.from can easily be polyfilled for older browsers.
Try it here.

Categories