Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
For example, I have an array like this;
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]
If an element is repeated remove it completely
var arr = [1, 3, 4, 6, 8, 9]
Any tips, link or code example would be useful.
Thank you in advance!
Filter out items with more than 1 index
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (item, index, arr) {
return arr.indexOf(item) == arr.lastIndexOf(item);
});
arr
/* returned value: (Array)
1,3,4,6,8,9
*/
There is no need for a library, ES ed 3 support is sufficient. If the array is sorted per the OP, then:
function removeDups(a) {
var i = a.length && a.length - 1;
while (i) {
if (a[i] == a[--i]) {
a.splice(i, 1);
}
}
// Not required, but convenient
return a;
}
Edit
To remove all duplicates "completely" with an unsorted array (works with primitive or object values), consider:
// Removes duplicated elements comlpetely,
// e.g. [1,1,2,3,3] => [2]
// Requires ES5 Array.prototype.indexOf
function removeDupsUnsorted(a) {
var i = a.length;
var idx, v;
while (--i > -1) {
v = a[i];
idx = a.indexOf(v);
if (idx != i) {
do {
a.splice(idx, 1);
idx = a.indexOf(v);
i--;
} while (idx != -1)
++i;
}
}
return a;
}
Here is potentially an O(n) solution, assuming property lookup and insertion are O(1):
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
var included = arr.reduce( function(a,b) {
a[b] = a[b]===undefined; return a}, {} );
arr.filter( function(c) { return included[c]; } )
// [1, 3, 4, 6, 8, 9]
It is actually faster with direct for loops rather than reduce and filter:
function removeDups5(a) {
var included = {}, i;
for( i=0 ; i<a.length ; ++i ) included[a[i]] = a[i] in included;
for( --i ; 0<=i ; --i ) if(included[a[i]]) a.splice(i,1);
return a;
}
Here is a jsperf comparing some of these answers to each other. This solution is currently in the lead, it seems, the longer the array is. (Anyone feel free to add your solution to it.)
You can use filter:
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (item, index, arr) {
return arr.indexOf(item) == arr.lastIndexOf(item);
});
console.log(arr); // [1, 3, 4, 6, 8, 9]
Fiddle Demo
I'm a little tired, but this should also do the trick (ECMA5) and original order should not matter.
Javascript
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (value, index, array) {
return (!this[value] && array.lastIndexOf(value) === index) || !(this[value] = true);
}, {});
console.log(JSON.stringify(arr));
Output
[1,3,4,6,8,9]
On jsFiddle
Assuming arr is sorted, here is an O(n) solution.
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]; //Make sure it's sorted!
var no_add;
var other = [];
other.push(arr[0]);
for (var i = 1; i < arr.length; i++)
{
if(no_add == arr[i])
continue;
if(other[other.length - 1] == arr[i])
{
no_add = other.pop();
continue;
}
else
other.push(arr[i]);
}
console.log(other); //[1, 3, 4, 6, 8, 9]
Related
This question already has answers here:
Split array into chunks
(73 answers)
Closed 20 days ago.
I am studying algorithms in JavaScript; I am trying to generate consecutive subarrays but I don't know to do it.
I have the following array:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
I want to split it in subarrays of size 3 using iteration:
[1, 2, 3] [4, 5, 6] [7, 8, 9]
I know how to do a subarray using slice(), but as I told I want to do consecutive subarrays with size k.
function ub(a) {
let resposta = []
for (let i = 0 ; i < a.length; i++) {
resposta = a.slice(2, 5)
}
return resposta
}
console.log(ub([2, 37, 8, 9, 23, 34, 44]))
Increment the index by the subarray size each time, then slice that number of elements from the current index on each iteration.
function ub(arr, k) {
let res = [];
for (let i = 0; i < arr.length; i += k) res.push(arr.slice(i, i + k));
return res;
}
console.log(JSON.stringify(ub([1,2,3,4,5,6,7,8,9], 3)));
You can use this way
function ub(a) {
return a.reduce((acc, val, index) => {
if (index % 3 === 0) {
acc.push(a.slice(index, index + 3));
}
return acc;
}, []);
}
console.log(JSON.stringify(ub([1, 2, 3, 4, 5, 6, 7, 8, 9])));
or you can use Array.from
function ub(a) {
return Array.from({ length: Math.ceil(a.length / 3) }, (_, i) =>
a.slice(i * 3, i * 3 + 3)
);
}
console.log(JSON.stringify(ub([1, 2, 3, 4, 5, 6, 7, 8, 9])));
First off am a beginner practicing my JavaScript. My solution to this problem will be posted. I think its worth mentioning this took almost two days of pondering to solve
The Problem:
I am required to write an algorithm that will return the mode(s) from the given input array. For example:
mode([4, 5, 6, 6, 6, 7, 7, 9, 10]) ➞ [6]
mode([4, 5, 5, 6, 7, 8, 8, 9, 9]) ➞ [5, 8, 9]
mode([1, 2, 2, 3, 6, 6, 7, 9]) ➞ [2, 6]
Solution:
function mode(nums) {
let array = [...nums]
array = array.sort((a, b) => a - b) //sorts the array from lowest value
// function to figure out the unique numbers and return as an array
function uniqueNums(array) {
let uniques = []
for (let i = 0; i < array.length; i++) {
if (!uniques.includes(array[i])) {
uniques.push(array[i])
}
}
return uniques
}
//function to return the mode of every unique number
function counter(array) {
let modes = []
for (let i = 0; i < array.length; i++) {
let count = 1, // keeps track of occurrence's of a number
track = 1 //variable enables the while loop keep checking
while (array[i] === array[i + track]) {
count++
track++
}
modes.push(count)
i += count - 1
}
return modes
}
//function to return the highest mode(s)
function highestMode(uniques, modes) {
let highest = [],
max = 0 //tracks our highest number in the array
//loops to find highest mode
for (let i = 0; i < modes.length; i++) {
if (max < modes[i]) {
max = modes[i]
}
}
//loops to push position of modes equal to the highest mode
for (let i = 0; i < modes.length; i++) {
if (max === modes[i]) {
highest.push(i)
}
}
//uses the position of highest modes to swap them with their
//actual values
let result = highest.map(a => a = uniques[a])
return result
}
return highestMode(uniqueNums(array), counter(array))
}
console.log(mode([4, 4, 4, 6, 8, 9, 10, 10]))
If you're looking at this as a learning exercise, here's another implementation of the same algorithm from CertainPerformance, but written quite differently.
const mode = (
ns,
counts = ns .reduce ((m, n) => m .set (n, (m .get (n) || 0) + 1), new Map ()),
max = Math .max (... counts .values())
) =>
[...counts] .flatMap (([n, c]) => c == max ? [n] : [])
console .log (mode ([4, 5, 6, 6, 6, 7, 7, 9, 10])) //=> [6]
console .log (mode ([4, 5, 5, 6, 7, 8, 8, 9, 9])) //=> [5, 8, 9]
console .log (mode ([1, 2, 2, 3, 6, 6, 7, 9])) //=> [2, 6]
If it's not clear, my counts matches to grouped and my max to maxCount.
The big difference from the answer by CertainPerformance is that this is written with pure expressions rather than statements. This is a style that I try to follow as much as I can do so practically.
It uses default parameters as a poor-man's substitute for let bindings available in other languages. It's not a perfect substitute and there is at least one potential problem with it, but it can be quite useful. Doing this let me define some helper variables that you can't assign in a function body without statements. There are alternatives, but I find this simplest when I can get away with it.
The reduce call is essentially the same as the other answer. So is the max definition.
But I take advantage of the fact that the default iterator of a Map is the list of entries, to turn the map into [[4, 1], [5, 1], [6, 3] ...] just by using the spread operator (...), without a need to call .entries().
Finally, I replace a call to filter and then to map with a single call to flatMap. This feels more elegant.
I'm not trying to suggest that this code is better than the one from CertainPerformance. It's quite similar in feel, although different in arrangement. But it is a different approach to the problem, and it might have something to offer because of that.
I'd count up the number of occurrences of each element into an Map. Then use Math.max to find the largest value(s) in the map, and then take the keys which are equal to that largest value:
const mode = arr => {
const grouped = new Map();
for (const item of arr) {
grouped.set(item, (grouped.get(item) || 0) + 1);
}
const maxCount = Math.max(...grouped.values());
return [...grouped.entries()]
.filter(([, count]) => count === maxCount)
.map(([key]) => key);
};
console.log(mode([4, 5, 6, 6, 6, 7, 7, 9, 10])) // ➞ [6]
console.log(mode([4, 5, 5, 6, 7, 8, 8, 9, 9])) // ➞ [5, 8, 9]
console.log(mode([1, 2, 2, 3, 6, 6, 7, 9])) // ➞ [2, 6]
A more simpler and optimized approach with single iteration
https://jsfiddle.net/dv7f9nxr/
function mode(items) {
var result = [];
var count = {};
var highest= 0;
items.map((item) => {
var itemCount = (count[item] || 0) + 1;
count[item] = itemCount;
if(itemCount > highest) {
highest = itemCount;
//reset
result = [item];
} else if (itemCount === highest){
result.push(item);
}
})
return result;
}
console.log(mode([2, 3, 9, 6, 9]))
console.log(mode([2, 3,2, 9, 6, 9]))
console.log(mode([2, 3,2, 9, 6, 9,2]))
console.log(mode([2, 3, 9, 6, 9,6,2]))
I am taking an excercise on codewars:
Given a list of integers and a single sum value, return the first two
values (parse from the left please) in order of appearance that add up
to form the sum.
Example:
sum_pairs([10, 5, 2, 3, 7, 5], 10)
# ^-----------^ 5 + 5 = 10, indices: 1, 5
# ^--^ 3 + 7 = 10, indices: 3, 4 *
# * entire pair is earlier, and therefore is the correct answer
== [3, 7]
What do you think entire pair is earlier means? IMO if the sum of it's indexes is smallest. Now based on this assumption I made my solution and one test fails:
var sum_pairs=function(ints, s){
let i = 0;
let pair = [0, 0];
let ind = [100, 100]
let found = false;
function loop(i) {
if (i > ints.length) return pair;
ints.slice(i).forEach((curr, idx) => {
ints.slice(i+1).some((num, i) => {
let sum = curr + num;
let prevIndicies = ind[0] + ind[1];
if(sum === s && prevIndicies > idx + i) {
ind = [idx, i];
pair = [curr, num];
found = true;
return true;
}
})
})
i += 1;
loop(i)
}
loop(0)
if (found) {
return pair
}
return undefined;
}
console.log(sum_pairs([1,4,8,7,3,15], 8))
Test returns error that [1, 7] is expected.
I'm pretty sure what it means is they want the second element to be as leftward in the list as possible. For example, for
l5= [10, 5, 2, 3, 7, 5];
when trying to find a sum of 10, the desired output is
[3, 7]
[10, 5, 2, 3, 7, 5];
^ ^
instead of
[5, 5]
[10, 5, 2, 3, 7, 5];
^ ^
because the last element in [3, 7], the 7, came before the second 5.
This code seems to pass all test cases - iterate in a triangular fashion, starting at indicies [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3], ...:
const sum_pairs = function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
const sum_pairs=function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
l1= [1, 4, 8, 7, 3, 15];
l2= [1, -2, 3, 0, -6, 1];
l3= [20, -13, 40];
l4= [1, 2, 3, 4, 1, 0];
l5= [10, 5, 2, 3, 7, 5];
l6= [4, -2, 3, 3, 4];
l7= [0, 2, 0];
l8= [5, 9, 13, -3];
console.log(sum_pairs(l1, 8))
console.log(sum_pairs(l2, -6))
console.log(sum_pairs(l3, -7))
console.log(sum_pairs(l4, 2))
console.log(sum_pairs(l5, 10))
console.log(sum_pairs(l6, 8))
console.log(sum_pairs(l7, 0))
console.log(sum_pairs(l8, 10))
It means that you go from left to right and take the first matching pair, and since 7 is the first element that creats a pair (going from the left) 3 and 7 is the first pair.
I would solve it a bit easier:
function sum_pairs(arr, target) {
let old = [];
let result = [];
arr.some((el) => {
let found = old.find((oldEl) => oldEl + el === target);
if (found) return result = [found, el];
old.push(el);
})
return result;
}
sum_pairs([10, 5, 2, 3, 7, 5], 10);
Edit: an explaination. I loop over all elements in the array searching for a match i all the elements I have passed. If I find a match I remember it and break out of the loop by returning a "truthy" value. (That is just how .some() works.) Finally if I have not found a match I add the element to my list of old elements and go on to the next.
function sum_pair(arr,sum){
let result = [];
arr.forEach((i, j)=>{
if(i+arr[j+1]===sum){
console.log(i,arr[j+1], i+arr[j+1])
}
})
}
sum_pair([0, 3, 7, 0, 5, 5],10)
I want a function that returns the sub array which takes a position & the no. of elements I want. I think there may be some algorithm to find the pivot point or something & from that I can get the sub array, but I totally forgot it.
Example: a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I want 6 elements
if position = 0, then I want [1, 2, 3, 4, 5, 6]
if position = 1, then [1, 2, 3, 4, 5, 6]
if position = 2, then [1, 2, 3, 4, 5, 6]
if position = 3, then [1, 2, 3, 4, 5, 6]
if position = 4, then [2, 3, 4, 5, 6, 7]
if position = 5, then [3, 4, 5, 6, 7, 8]
if position = 6, then [4, 5, 6, 7, 8, 9]
if position = 7, then [5, 6, 7, 8, 9, 10]
if position = 8, then [5, 6, 7, 8, 9, 10]
if position = 9, then [5, 6, 7, 8, 9, 10]
simply get the middle of N elements based on the position I pass.
I can write up my own loop which will contain multiple if-else conditions to get it done. But I feel there may be some easy way to do it.
I didnt include my incomplete code snippet because I strongly feel there must be some algorithm to do this.
What you want is : Array.prototype.slice(...)
It's neatly documented here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
var n = 6;
var start = Math.max(0, Math.min(Math.floor(position-n/2), a.length-n));
return a.slice(start, start+n);
Simple way:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
function getSubArray(idx, _length, _array) {
return _array.slice(idx, idx + _length);
}
var subArray = getSubArray(3, 6, a);
You could use an offset for the postion and get the the start value first for slicing.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
n = 6,
i,
start;
for (i = 1; i < 12; i++) {
start = Math.max(Math.min(i - n / 2, a.length - n), 0);
console.log(i, ': ', a.slice(start, start + n).join());
}
Your only need is to check if you are not gonna check a pos that doesn't exist. Like :
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var n = 6; // Number of result you want
var x = 8; // Pos you want
// If you gonna exceed your length, we got only the n last element
if((x+(n/2)) > a.length) {
console.log(a.slice(a.length-n));
// Otherwise, if under 0, we got the n first
} else
if((x-(n/2)) < 0) { console.log(a.slice(0,n) );
// Default case
} else {
console.log(a.slice((x-(n/2)),(x+(n/2))));
}
This is not the smartest way, but he can give you some hint. I used the slice as other mentionned to avoid a lot of if, but you should do GENERIC test.
Something like this :
a = [1,2,3,4,5,6,7,8,9,10];
n = 6;
function split(position) {
var start = Math.min(Math.max(position - Math.floor(n/2), 0), a.length - n);
var stop = Math.min(start+n, a.length);
return a.slice(start, stop);
}
No need for the Math object at all. You may simply do as follows;
function getArr(a,n,d){
n = n - 4 < 0 ? 0
: a.length - d > n - 4 ? n - 3
: a.length - d;
return a.slice(n,n + d);
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
diff = 6;
for (var i = 0; i < 10; i ++) console.log(JSON.stringify(getArr(arr,i,diff)));
no need of if-else you can use arr[position] to arr[8]. have you got
function getArr(arr,position,requiredNumbers){
return arr.slice(position, position+requiredNumbers);
}
I'm trying to create a sum function. When I run it through two different arrays (with same values), it's giving me different results. I can't really tell where I did wrong. It seems when I'm generating the array using the 'range' function, it's looping twice.
var myArr = [];
var tempArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function range(start, end) {
for (i = start; i <= end; i++) {
myArr.push(start);
start = start + 1;
}
return myArr;
}
function sum(arr) {
var sumArr = 0;
for (i = 0; i < arr.length; i++) {
sumArr = sumArr + arr[i];
//console.log(sumArr);
}
return sumArr;
}
console.log(range(1, 10)); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(tempArr); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(sum(range(1, 10))); //110
console.log(sum(tempArr)); //55
Any help would be appreciated. Thanks!
The reason is that var myArr = []; was a global variable. So pushed elements in the first console attempt will be there until they are cleared. You can use local variable in the function instead.
var tempArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function range(start, end) {
var myArr = [];
for (i = start; i <= end; i++) {
myArr.push(start);
start = start + 1;
}
return myArr;
}
function sum(arr) {
var sumArr = 0;
for (i = 0; i < arr.length; i++) {
sumArr = sumArr + arr[i];
//console.log(sumArr);
}
return sumArr;
}
console.log(range(1, 10)); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(tempArr); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(sum(range(1, 10))); //55
console.log(sum(tempArr)); //55
Using lodash :
You can use ._sum function.
var tempArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum = _.sum(tempArr)
Don't forget to add the library if you want to use it.
<script src="https://cdn.jsdelivr.net/lodash/4.5.1/lodash.min.js"></script>
Demo