splice function does not work properly in 1 items array - javascript

In my Laravel 5/vuejs 2/ vuex app I make deletion of an row in db and use splice function to remove item from the array as:
axios({
method: ( 'delete' ),
url: this.getters.apiUrl + '/personal/hostel_bookmarks/' + this.getters.currentLoggedUser.id + "/" + relatedHostel.id,
}).then((response) => {
let L = this.getters.hostelBookmarks.length
for (var I = 0; I < L; I++) {
if (relatedHostel.id == this.getters.hostelBookmarks[I].hostel_id) {
// this.getters.hostelBookmarks.splice(this.getters.hostelBookmarks.indexOf(this.getters.hostelBookmarks[I]), 1)
this.getters.hostelBookmarks.splice(I, 1)
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
break;
}
}
bus.$emit( 'onHostelBookmarkDeleteSuccess', response );
}).catch((error) => {
bus.$emit('onHostelBookmarkDeleteFailure', error);
});
It works ok if this.getters.hostelBookmarks has more 1 elements, but if it has only 1 items then it is not deleted, but how error in js console...
How to fix ?

This should fix your problem
let index = this.getters.hostelBookmarks.findIndex(item => { return item.hostel_id === relatedHostel.id })
if (index !== -1) {
this.getters.hostelBookmarks.splice(index, 1)
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
}

Can you try the following code?
let L = this.getters.hostelBookmarks.length;
for (var I = L-1; I >= 0; I--) {
if (relatedHostel.id == this.getters.hostelBookmarks[I].hostel_id) {
this.getters.hostelBookmarks.splice(I, 1);
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
break;
}
}
demo code for ++, --:
If you have an array [1, 2, 3, 4, 5]. And you want to remove the 2nd and 4th element, 2 and 4.
First ++:
const origin = [1,2,3,4,5];
for(var i = 0; i < origin.length; i++){
if(i === 1 || i === 3) {
origin.splice(i, 1);
}
}
console.log(origin); // [1, 3, 4]
As you can see, the result is not you expected. If you log the every element in loop, you will see the index of element was changed after the element 2 was deleted. When i is 3 in the loop, actually, the 5th element will be deleted.
Then let's have a look in --:
const origin = [1,2,3,4,5];
for(var i = origin.length; i >= 0; i--){
if(i === 3 || i === 1) {
origin.splice(i, 1);
}
}
console.log(origin); // [1, 3, 5]
This is what you want. When --, we will remove the element from the last to the first. The index of element is not changed.

Related

Get permutations of all the array [1, 1, 1, 1, 1, 0, 0, 0, 0]

I am trying to create a script which generates all the various permutations of binary switches where there should be 5 1 and 4 0. And the array should be of size 9.
I tried the following code. The conditions for the permutations are:
1. The array set should be unique.
2. Not more than 3 1 should be next to each other
const row = [1, 1, 1, 1, 1, 0, 0, 0, 0];
const list = [];
const fullList = [];
// To make sure that no more than 3 `1` are next to each other
const isRowValid = (row) => {
let isValid = true;
for(let i = 0; i+2 < row.length; i++) {
if(row[i] === 1 && row[i+1] === 1 && row[i+2] === 1) {
isValid = false;
break;
}
}
return isValid;
}
const combinations = (row, baseIndex, currentIndex, iterationLevel, list) => {
if(currentIndex > row.length - iterationLevel) {
baseIndex++;
currentIndex = 0;
}
if(baseIndex + iterationLevel > row.length) {
baseIndex = 0;
iterationLevel++;
}
if(iterationLevel === 5) {
return;
}
let rowCopy = [...row]
if(baseIndex > currentIndex ) {
let first = [...row.slice(0, currentIndex)];
let second = [...row.slice(currentIndex)];
let value = second.splice(baseIndex - currentIndex, iterationLevel);
rowCopy = [...first, ...value, ...second]
} else if(baseIndex < currentIndex) {
let first = [...row.slice(0, currentIndex + iterationLevel)];
let second = [...row.slice(currentIndex + iterationLevel)];
let value = first.splice(baseIndex, iterationLevel);
rowCopy = [...first, ...value, ...second];
}
if(isRowValid(rowCopy)) {
list.push(rowCopy);
}
console.log(rowCopy);
combinations(row, baseIndex, currentIndex + 1, iterationLevel, list);
}
combinations(row, 0, 0, 1, list);
list.forEach(l => combinations(l, 0, 0, 1, fullList));
// To remove duplicates
for(let i = 0; i < fullList.length; i++) {
const base = fullList[i]
for(let j = i + 1; j < fullList.length; j++) {
const isSame = fullList[j].every((l, m) => base[m] === l);
if(isSame) {
fullList[j] = [];
}
}
}
let filtered = fullList.filter(l => l.length !== 0);
console.log(filtered.length);
filtered.slice(0, 100).map(i => console.log(i));
console.log(fullList.length);
JS Bin
If I understand correctly, you meant permutations rather than combinations, where in each permutation there shouldn't be more than 3 sequential switches that are "on".
Whenever you have to generate permutations or combinations you can use a recursive backtracking algorithm.
The idea is simple, at every step you follow the possible choices until a base condition is met (e.g. permutation is complete because perm.length === switchCount). When taking a step you reflect that choice on the problem's state and when the recursive call returns you undo these effects.
In order to determine what choices can be made at each step we need to keep track of the problem's state. Here we only need to know how many on/off switches we have left and how many sequential on switches we have so far (seqOn).
const perms = permute(5, 4);
console.log(perms.length);
console.log(perms);
function permute(on, off) {
const switchCount = on + off;
const perm = [], perms = [];
p(on, off, 0);
return perms;
function p(on, off, seqOn) {
if (perm.length === switchCount) {
perms.push([...perm]);
return;
}
if (on && seqOn < 3) {
perm.push(1);
p(on - 1, off, seqOn + 1);
perm.pop();
}
if (off) {
perm.push(0);
p(on, off - 1, 0);
perm.pop();
}
}
}
If we have many permutations to enumerate we can save on memory by using generators too. Here I yield the same perm array which saves the O(n) time copy. As long as you don't need to keep a copy and just enumerate switches it's fine.
for (const perm of permute(5, 4)) {
console.log(perm);
}
function* permute(on, off) {
const switchCount = on + off;
const perm = [];
yield* p(on, off, 0);
function* p(on, off, seqOn) {
if (perm.length === switchCount) {
yield perm;
return;
}
if (on && seqOn < 3) {
perm.push(1);
yield* p(on - 1, off, seqOn + 1);
perm.pop();
}
if (off) {
perm.push(0);
yield* p(on, off - 1, 0);
perm.pop();
}
}
}

How can I check if an array includes another array? [duplicate]

I needed 2d arrays, so I made a nested array since JavaScript doesn't allow them.
They look like this:
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
How can I check if this array includes a specific element (i.e. one of these [0,1] arrays) in vanilla JS?
Here is what I tried, with no success (everything returns false) (EDIT: I included the answers in the snippet):
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
var itemTrue = [2, 4];
var itemFalse = [4, 4];
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
// EDIT: first answer's solution
function isArrayInArray(x, check) {
for (var i = 0, len = x.length; i < len; i++) {
if (x[i][0] === check[0] && x[i][1] === check[1]) {
return true;
}
}
return false;
}
// EDIT: accepted answer's solution
function isArrayInArray2(x, check) {
var result = x.find(function(ele) {
return (JSON.stringify(ele) === JSON.stringify(check));
})
return result !=null
}
console.log("true :" + myArray.includes(itemTrue));
console.log("false :" + myArray.includes(itemFalse));
console.log("true :" + (myArray.indexOf(itemTrue) != -1));
console.log("false :" + (myArray.indexOf(itemFalse) != -1));
console.log("true :" + contains(myArray, itemTrue));
console.log("false :" + contains(myArray, itemFalse));
// EDIT: first answer's solution
console.log("true :" + isArrayInArray(myArray, itemTrue));
console.log("false :" + isArrayInArray(myArray, itemFalse));
// EDIT: accepted answer's solution
console.log("true :" + isArrayInArray2(myArray, itemTrue));
console.log("false :" + isArrayInArray2(myArray, itemFalse));
It could look like duplicate but I couldn't find a similar question. If it is, feel free to tag it as such.
Short and easy, stringify the array and compare as strings
function isArrayInArray(arr, item){
var item_as_string = JSON.stringify(item);
var contains = arr.some(function(ele){
return JSON.stringify(ele) === item_as_string;
});
return contains;
}
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
var item = [1, 0]
console.log(isArrayInArray(myArray, item)); // Print true if found
check some documentation here
A nested array is essentially a 2D array, var x = [[1,2],[3,4]] would be a 2D array since I reference it with 2 index's, eg x[0][1] would be 2.
Onto your question you could use a plain loop to tell if they're included since this isn't supported for complex arrays:
var x = [[1,2],[3,4]];
var check = [1,2];
function isArrayInArray(source, search) {
for (var i = 0, len = source.length; i < len; i++) {
if (source[i][0] === search[0] && source[i][1] === search[1]) {
return true;
}
}
return false;
}
console.log(isArrayInArray(x, check)); // prints true
Update that accounts for any length array
function isArrayInArray(source, search) {
var searchLen = search.length;
for (var i = 0, len = source.length; i < len; i++) {
// skip not same length
if (source[i].length != searchLen) continue;
// compare each element
for (var j = 0; j < searchLen; j++) {
// if a pair doesn't match skip forwards
if (source[i][j] !== search[j]) {
break;
}
return true;
}
}
return false;
}
console.log(isArrayInArray([[1,2,3],[3,4,5]], [1,2,3])); // true
You can't do like that .instance you have to do some thing by your own ..
first you have to do a foreach from your array that you want to search and run 'compareArray' function for each item of your array .
function compareArray( arrA, arrB ){
//check if lengths are different
if(arrA.length !== arrB.length) return false;
for(var i=0;i<arrA.length;i++){
if(arrA[i]!==arrB[i]) return false;
}
return true;
}
Here is an ES6 solution:
myArray.some(
r => r.length == itemTrue.length &&
r.every((value, index) => itemTrue[index] == value)
);
Check the JSFiddle.
Take a look at arrow functions and the methods some and every of the Array object.
The code provided by D. Young's comment that checks for any length array is faulty. It only checks if the first element is the same.
A corrected version of D. Young's comment:
function isArrayInArray(source, search) {
var searchLen = search.length;
for (var i = 0, len = source.length; i < len; i++) {
// skip not same length
if (source[i].length != searchLen) continue;
// compare each element
for (var j = 0; j < searchLen; j++) {
// if a pair doesn't match skip forwards
if (source[i][j] !== search[j]) {
break;
} else if (j == searchLen - 1) {return true}
}
}
return false;
}
For those who are interested in finding an array inside another and get back an index number, here's a modified version of mohamed-ibrahim's answer:
function findArrayInArray(innerArray, outerArray) {
const innerArrayString = JSON.stringify(innerArray);
let index = 0;
const inArray = outerArray.some(function (element) {
index ++;
return JSON.stringify(element) === innerArrayString;
});
if (inArray) {
return index - 1;
} else {
return -1;
}
}
findArrayInArray([1, 2, 3], [[3, .3], [1, 2, 3], [2]]); // 1
findArrayInArray([1, 2, 3], [[[1], 2, 3], [2]]) // -1
This function returns the index of the array you are searching inside the outer array and -1 if not found.
Checkout this CodePen.

Check if an array is descending, ascending or not sorted?

I'm just beginning with programming using javascript and I need to practice some questions to get EXP with the logic of code build.
I got this question for homework but I can't make it work for some reason, even though it seems "logic" to me.
Check if an array is descending, ascending or not sorted using loops.
I'm just a noob so please try and help me figure this out as I only got to loops in my studies (:
this is the code I wrote:
var array = [1, 2, 3, 7 ];
var d = 0;
var c =0 ;
var b = 1;
var a = 0;
for (var i = 1; i <= array.length; i++)
{
if (array[c]<array[b] && a!== -1 ){
d = -1;
c =c+1;
b = b+1;
if(c==array.length){
console.log("asc");
break;
}else{
continue;
}
} else if (array[c]>array[b] && d!==-1 ){
a = -1;
d= d+1;
b = b+1;
if(i=array.length){
console.log("dsc");
break;
}else{continue;}
} else{
console.log("unsorted array");
break;
}
}
Array.prototype.every passes its predicate an index, which you can use to get an element’s predecessor:
function isAscending(arr) {
return arr.every(function (x, i) {
return i === 0 || x >= arr[i - 1];
});
}
Here, we’re checking that every item (x) is greater than or equal to the item before it (arr[i - 1]) or has no item before it (i === 0).
Flip >= to <= for isDescending.
"Check if an array is descending, ascending or not sorted using loops"
// define the array
var array = [1,2,3,7];
// keep track of things
var isDescending = true;
var isAscending = true;
// we're looking ahead; loop from the first element to one before the last element
for (var i=0, l=array.length-1; i<l; i++)
{
////////////////////////////////////////////////////////////
// log to the console to show what's happening for each loop iteration
// this is the ith iteration
console.log("loop iteration %s", i);
// breaking isDescending down:
// is this value greater than the next value?
console.log("A: (%s > %s) = %s", array[i], array[i+1], (array[i] > array[i+1]));
// have all values been descending so far?
console.log("B: isDescending: %s", isDescending);
// if this value is greater than the next and all values have been descending so far, isDescending remains true. Otherwise, it's set to false.
console.log("are A and B both true? %s", (isDescending && (array[i] > array[i+1])));
// add a line break for clarity
console.log("");
////////////////////////////////////////////////////////////
// true if this is greater than the next and all other so far have been true
isDescending = isDescending && (array[i] > array[i+1]);
// true if this is less than the next and all others so far have been true
isAscending = isAscending && (array[i] < array[i+1]);
}
if (isAscending)
{
console.log('Ascending');
}
else if (isDescending)
{
console.log('Descending');
}
else
{
console.log('Not Sorted');
}
This is a question that requires some sort of loop, with several if statements because there are several cases you need to tackle:
Array is empty or has only one element.
All items in the array are equal
Array is ascending - delta between 2 elements > 0, but some deltas may be 0
Array is descending - delta between 2 elements < 0, but some deltas may be 0
Not sorted - some deltas are > 0, and some are < 0
Depending on how the sorted is defined in the question, cases 1 & 2 might be regarded as unsorted as well.
function findSortOrder(arr) {
if(arr.length < 2) { // case 1
return 'not enough items'; // can also be 'unsorted'
}
var ascending = null;
var nextArr = arr.slice(1); // create an array that starts from the 2nd element of the original array
for(var i = 0; i < nextArr.length; i++) {
if (nextArr[i] === arr[i]) { // neutral - do nothing
} else if(ascending === null) { // define the the direction by the 1st delta encountered
ascending = nextArr[i] > arr[i];
} else if (ascending !== nextArr[i] > arr[i]) { // case 5
return 'unsorted';
}
}
if(ascending === null) { // case 2
return 'all items are equal'; // can also be 'unsorted'
}
return ascending ? 'ascending' : 'descending'; // cases 3 & 4
}
console.log(findSortOrder([1])); // case 1
console.log(findSortOrder([1, 1, 1, 1])); // case 2
console.log(findSortOrder([1, 1, 2, 3, 7, 7])); // case 3
console.log(findSortOrder([7, 2, 2, 1])); // case 4
console.log(findSortOrder([7, 2, 1, 3, 2, 1])); // case 5
You could use a copy from the second element and check the predecessor for the wanted sort order.
function checkArray(array) {
var aa = array.slice(1);
if (!aa.length) {
return "Just one element";
}
if (aa.every((a, i) => array[i] > a)) {
return "Ascending";
}
if (aa.every((a, i) => array[i] < a)) {
return "Descending";
}
return "Unsorted";
}
console.log(checkArray([1, 2, 3, 4, 5]));
console.log(checkArray([5, 4, 3, 2, 1]));
console.log(checkArray([3, 1, 4, 2, 5]));
console.log(checkArray([42]));
function isAscending(arr = []) {
for (let i = 0; i < arr.length; i++) {
if (arr[i + 1] <= arr[i]) {
return false;
}
}
return true;
}
function isAscending(arr) {
return arr
.slice(1)
.every((num,i) => num >= arr[i]);
}
console.log(isAscending([1,2,3])); // true
console.log(isAscending([12,38,25])); // false
console.log(isAscending([103,398,52,629])); // false
arr.slice(1) --> allows us to start iteration at index 1 instead of 0
we'll iterate over "arr" with "every" & compare the current "num" against the previous "num" with "arr[i]"
function findOrder(array) {
var asc = true;
var desc = true;
if(array.length < 2){
return 'array is too small'
}
for(var i=1, len=array.length;i<len;i++){
//if current element is bigger than previous array is not descending
if(array[i]>array[i-1]){
desc = false;
//if current element is smaller than previous array is not ascending
}else if(array[i]<array[i-1]){
asc = false;
}
if(!asc && !desc){
return 'not sorted'
}
}
if(asc && desc){
return 'array values are equal'
}else if (asc){
return 'array is ascending'
}else {
return 'array is descending'
}
}
Actually we may do even more by creating an Array method like natureOf which can tell us more about the nature of the array than just ascending, descendig or flat. Array.natureOf() shall give us a value between -1 and 1. If it is -1 the array is fully descending and 1 would mean fully ascending of course. Any value inbetween would give us the inclination of the array. As you would guess 0 would mean totally random or flat. (it's fairly easy to insert the logic to distinguish random from flat if that's also needed)
Array.natureOf = function(a){
var nature = a.reduce((n,e,i,a) => i && a[i-1] !== e ? a[i-1] < e ? (n.asc++, n)
: (n.dsc++, n)
: n, {asc:0, dsc:0});
return (nature.asc - nature.dsc) / (a.length-1);
};
var arr = [1,2,3,4,5,6,7,8,9,10,7,11,13,14,15],
brr = Array.from({length:2000000}, _ => ~~(Math.random()*1000000000));
console.log(`The nature of "arr" array is ${Array.natureOf(arr)}`);
console.log(`The nature of "brr" array is ${Array.natureOf(brr)}`);
console.log(checkSort([1, 2, 3, 3, 4, 5]));
console.log(checkSort([5, 4, 3, 2, 1, 1]));
console.log(checkSort([2, 5, 8, 9, 4, 6]));
function checkSort(arr){
var isDescending, isAscending;
isDescending = isAscending = true;
const len = arr.length - 1;
for (var index = 0 ; index < len ; index++){
if(isAscending)
isAscending = arr[index] <= arr[index + 1];// '<=' so as to check for same elements
if(isDescending)
isDescending = arr[index] >= arr[index + 1];//'<=' so as to check for same elements
}
var result = "Array is ";
if (isAscending)
return result.concat("sorted in ascending order");
if (isDescending)
return result.concat("sorted in descending order");
return result.concat("not sorted");
const isAscending=(arr)=>{
for(let i=0;i<arr.length;i++){
if(arr[i+1]<arr[i]){ return false } } return true }

How to remove elements from array satisfying condition

I want to delete json elements which are satisfying the condition. For that I used the given code
var index = -1;
for (var i = 0; i < data.dashLayout.dashlets.length; i++) {
if (data.dashLayout.dashlets[i].rowNo == selectedrowno) {
if (index == -1 || data.dashLayout.dashlets[i].rowNo < data.dashLayout.dashlets[index].rowNo) {
index = i;
}
}
if (index != -1) {
data.dashLayout.dashlets.splice(index, 1);
}
}
But iteration is not completing because the data.dashLayout.dashlets.length is reducing with splice. How can I solve this issue? I want to delete all items that are satisfying the condition. Please help
Another two solutions
var a = [2,5,8,13,9,1,4,8,10], l = a.length, c = 5;
// using reverse loop
while(l--){
if(a[l] < c) a.splice(l, 1);
}
// using filter
var b = a.filter(function(e, c) {
return --e > c;
});
console.log(a); // [5, 8, 13, 9, 8, 10]
console.log(b); // [5, 8, 13, 9, 8, 10]
If you split the array in the loop .the array will be reducing you should not iterate fully , so you have to think different idea . so my solution is you have to store the index based on that you have to remove the array .In the mean time every time the index will be changed so you have to use -1
var index = -1;
var arr = [] // make array
for (var i = 0; i < data.dashLayout.dashlets.length; i++) {
if (data.dashLayout.dashlets[i].rowNo == selectedrowno) {
if (index == -1 || data.dashLayout.dashlets[i].rowNo < data.dashLayout.dashlets[index].rowNo) {
index = i;
}
}
if (index != -1) {
// data.dashLayout.dashlets.splice(index, 1);
arr.push(index); //stored it
}
}
// to remove
for(var i in arr){
if (i == 0) {
data.dashLayout.dashlets.splice(arr[i], 1); // to remove init
} else {
data.dashLayout.dashlets.splice(arr[i] - 1, 1); // now index is changed now use -1
}
}
I would recommend using the filter method of the Array object. Filter method will return a new array which only contains the elements you want. Please see the definition of the filter method here
The usage will be like the code below
var newDashlets = data.dashLayout.dashlets.filter(function(dashlet, i) {
// Here your code returns true if you want to keep dashlet.
// Return false if you don't want it.
});
in jquery
data.dashLayout.dashlets = $.grep(data.dashLayout.dashlets, function (dashList, indexpos) {
if (dashList.rowNo == selectedrowno) {
if (dashList.rowNo < data.dashLayout.dashlets[index].rowNo || index == -1) {
index = indexpos;
return false;
}
}
});
Using map in jquery
data.dashLayout.dashlets = $.map(data.dashLayout.dashlets, function (dashList, indexpos) {
if (dashList.rowNo == selectedrowno) {
if (dashList.rowNo < data.dashLayout.dashlets[index].rowNo || index == -1) {
index = indexpos;
} else {
return dashList;
}
}
});

deleting duplicates on sorted array

Just in case you missed, the question is about deleting duplicates on a sorted array. Which can be applied very fast algorithms (compared to unsorted arrays) to remove duplicates.
You can skip this if you already know how deleting duplicates on SORTED arrays work
Example:
var out=[];
for(var i=0,len=arr.length-1;i<len;i++){
if(arr[i]!==arr[i+1]){
out.push(arr[i]);
}
}
out.push(arr[i]);
See?, it is very fast. I will try to explain what just happened.
The sorted arrays *could look like this:
arr=[0,1,1,2,2,3,4,5,5,6,7,7,8,9,9,9];
*the sorting could be ASC or DESC, or by other weird methods, but the important thing is that every duplicated item is next each other.
We stopped at array.length-1 because we don't have anything to check with
Then we added the last element regardless of anything because:
case A:
... ,9,9,9];//we have dup(s) on the left of the last element
case B:
... ,7,9,10];//we don't have dup(s) on the left of the last element
If you really understand what is happening, you will know that we haven't added any 9 on the case A. So because of that, we want to add the last element no matter if we are on case A or B.
Question:
That explained, I want to do the same, but ignoring the undefined value on cases like:
var arr=[];arr[99]=1;//0 through 98 are undefined, but do NOT hold the undefined value
I want to remove those. And on the case I have some real undefined values, these should not be removed.
My poor attempt is this one:
var out=[];
for (var i=0,len=arr.length; i < len - 1;) {
var x = false;
var y = false;
for (var j = i, jo; j < len - 1; j++) {
if (j in arr) {
x = true;
jo = arr[j];
i = j + 1;
break;
}
}
if (x == false) {
break;
}
for (var u = i, yo; u < len - 1; u++) {
if (u in arr) {
y = true;
yo = arr[u];
i = u + 1;
break;
}
}
if (y == false) {
out.push(jo);
break;
}
if (jo !== yo) {
out.push(jo);
}
}
out.push(arr[len - 1]);
I am really lost, any help is appreciated
A modern one-liner using .filter()
arr.filter((e, i, a) => e !== a[i - 1]);
I'm very surprised by the complexity of other answers here, even those that use .filter()
Even using old-school ES5 syntax with no arrow functions:
arr.filter(function (e, i, a) { return e !== a[i - 1] });
Example:
let a = [0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 9];
let b = arr.filter((e, i, a) => e !== a[i - 1]);
console.log(b); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
If you need to mutate the array in place then just use:
arr = arr.filter((e, i, a) => e !== a[i - 1]);
Personally I would recommend against using such complex solutions as the ones in other answers here.
For a start, I'm not entirely certain your original code is kosher. It appears to me that it may not work well when the original list is empty, since you try to push the last element no matter what. It may be better written as:
var out = [];
var len = arr.length - 1;
if (len >= 0) {
for (var i = 0;i < len; i++) {
if (arr[i] !== arr[i+1]) {
out.push (arr[i]);
}
}
out.push (arr[len]);
}
As to your actual question, I'll answer this as an algorithm since I don't know a lot of JavaScript, but it seems to me you can just remember the last transferred number, something like:
# Set up output array.
out = []
# Set up flag indicating first entry, and value of last added entry.
first = true
last = 0
for i = 0 to arr.length-1:
# Totally ignore undefined entries (however you define that).
if arr[i] is defined:
if first:
# For first defined entry in list, add and store it, flag non-first.
out.push (arr[i])
last = arr[i]
first = false
else:
# Otherwise only store if different to last (and save as well).
if arr[i] != last:
out.push (arr[i])
last = arr[i]
This is a one-liner:
uniquify( myArray.filter(function(x){return true}) )
If you don't already have uniquify written (the function you wrote to remove duplicates), you could also use this two-liner:
var newArray = [];
myArray.forEach(function(x) {
if (newArray.length==0 || newArray.slice(-1)[0]!==x)
newArray.push(x)
})
Elaboration:
var a=[];
a[0]=1; a[1]=undefined; a[2]=undefined;
a[10]=2; a[11]=2;
According to OP, array has "five elements" even though a.length==12. Even though a[4]===undefined, it is not an element of the array by his definition, and should not be included.
a.filter(function(x){return true}) will turn the above array into [1, undefined, undefined, 2, 2].
edit: This was originally written with .reduce() rather than .forEach(), but the .forEach() version is much less likely to introduce garbage-collector and pass-by-value issues on inefficient implements of javascript.
For those concerned about compatibility with the 6-year-old MIE8 browser, which does not support the last two editions of the ECMAScript standard (and isn't even fully compliant with the one before that), you can include the code at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach However if one is that concerned about browser compatibility, one ought to program via a cross-compiler like GWT. If you use jQuery, you can also rewrite the above with only a few extra characters, like $.forEach(array, ...).
Perhaps something like this:
var out = [],
prev;
for(var i = 0; i < arr.length; i++) {
if (!(i in arr))
continue;
if (arr[i] !== prev || out.length === 0) {
out.push(arr[i]);
prev = arr[i];
}
}
The out.length check is to allow for the first defined array element having a value of undefined when prev also starts out initially as undefined.
Note that unlike your original algorithm, if arr is empty this will not push an undefined value into your out array.
Or if you have a new enough browser, you could use the Array.forEach() method, which iterates only over array elements that have been assigned a value.
An explicit way would be to pack the array (remove the undefined) values and use your existing algorithm for the duplicates on that..
function pack(_array){
var temp = [],
undefined;
for (i=0, len = _array.length; i< len; i++){
if (_array[i] !== undefined){
temp.push(_array[i]);
}
}
return temp;
}
I think this is what you want. It's a pretty simple algorithm.
var out = [], previous;
for(var i = 0; i < arr.length; i++) {
var current = arr[i];
if(!(i in arr)) continue;
if(current !== previous) out.push(current);
previous = arr[i];
}
This will run in O(N) time.
A very simple function, the input array must be sorted:
function removeDupes(arr) {
var i = arr.length - 1;
var o;
var undefined = void 0;
while (i > 0) {
o = arr[i];
// Remove elided or missing members, but not those with a
// value of undefined
if (o == arr[--i] || !(i in arr)) {
arr.splice(i, 1);
}
}
return arr;
}
It can probably be more concise, but might become obfuscated. Incidentally, the input array is modified so it doesn't need to return anything but it's probably more convenient if it does.
Here's a forward looping version:
function removeDupes2(arr) {
var noDupes = [],
o;
for (var i=0, j=0, iLen=arr.length; i<iLen; i++) {
o = arr[i];
if (o != noDupes[j] && i in arr) {
noDupes.push(o);
j = noDupes.length - 1;
}
}
return noDupes;
}
PS
Should work on any browser that supports javascript, without any additional libraries or patches.
This solution removes duplicates elements in-place. not recommended for functional programming
const arr =[0,0,1,1,2,2,2,3,4,5,5,6,7,7,8,9,9,9];
const removeDuplicates = (nums) => {
nums.forEach((element, idx) => {
nums.splice(idx, nums.lastIndexOf(element) - idx)
})
}
removeDuplicates(arr)
console.log(arr);
//sort the array
B.sort(function(a,b){ return a - b});
//removing duplicate characters
for(var i=0;i < B.length; i ++){
if(B[i]==B[i + 1])
B.splice(i,1)
}
if element in next index and current position is same remove the element at
current position
splice(targetPosition,noOfElementsToBeRemoved)
I believe what you are trying to achieve is not quite possible, but I could be wrong.
It's like one of those classic CS problems like the one where a barber in a village only shaves the one who don't shave themselves.
If you set the value of an array's index item as undefined, it's not really undefined.
Isn't that the case? A value can only be undefined when it hasn't been initialized.
What you should be checking for is whether a value is null or undefined. If null or duplicate skip the value, else retain it.
If null values and duplicates are what you are trying to skip then below function will do the trick.
function removeDuplicateAndNull(array){
if(array.length==0)
return [];
var processed = [], previous=array[0];
processed.push(array[0]);
for(var i = 1; i < array.length; i++) {
var value = array[i];
if( typeof value !== 'undefined' && value ==null)
continue;
if(value !== previous || typeof value === 'undefined')
processed.push(value);
previous = array[i];
}
return processed;
}
Test cases:
array=[,5,5,6,null,7,7] output =[ ,5,6,7]
array=[ 5,5,,6,null,,7,7] output=[5,,6,,7]
array=[7,7,,] output=[7,]
But even with this function there's a caveat. IF you check third test, the output is [7,]
instead of [7,,] !
If you check the length of the input and output arrays, array.length =3 and output.length=2.
The caveat is not with the function but with JavaScript itself.
This code is written in javascript. Its very simple.
Code:
function remove_duplicates(arr) {
newArr = [];
if (arr.length - 1 >= 0) {
for (i = 0; i < arr.length - 1; i++) {
// if current element is not equal to next
// element then store that current element
if (arr[i] !== arr[i + 1]) {
newArr.push(arr[i]);
}
}
newArr.push(arr[arr.length - 1]);
}
return newArr
}
arr=[0,1,1,2,2,3,4,5,5,6,7,7,8,9,9,9];
console.log(remove_duplicates(arr));
Here is the simple JavaScript solution without using any extra space.
function removeDuplicates(A) {
let i = 0;
let j = i + 1;
while (i < A.length && j < A.length) {
if (A[i] === A[j]) {
A.splice(i, 1);
j=i+1;
} else {
i++;
j++;
}
}
return A;
}
console.log('result', removeDuplicates([0,1,1,2,2,2,2,3,4,5,6,6,7]))
You can try the simple way
function hello(a: [], b: []) {
return [...a, ...b];
}
let arr = removeDuplicates(hello([1, 3, 7], [1, 5, 10]));
arr = removeDuplicates(arr);
function removeDuplicates(array) {
return array.filter((a, b) => array.indexOf(a) === b);
}
let mainarr = arr.sort((a, b) => parseInt(a) - parseInt(b));
console.log(mainarr); //1,3,5,7,10
One liner code
[1,3,7,1,5,10].filter((a, b) => [1,3,7,1,5,10].indexOf(a) === b).sort((a, b) => parseInt(a) - parseInt(b))
Here is simple solution to remove duplicates from sorted array.
Time Complexity O(n)
function removeDuplicate(arr) {
let i=0;
let newArr= [];
while(i < arr.length) {
if(arr[i] < arr[i+1]) {
newArr.push(arr[i])
} else if (i === (arr.length-1)) {
newArr.push(arr[i])
}
i++;
}
return newArr;
}
var arr = [1,2,3,4,4,5,5,5,6,7,7]
console.log(removeDuplicate(arr))
Let's suppose that you have a sorted array and you can't use additional array to find and delete duplicates:
In Python
def findDup(arr, index=1, _index=0):
if index >= len(arr):
return
if arr[index] != arr[_index]:
findDup(arr, index+1, _index+1)
if arr[index] == arr[_index]:
arr = deletedup(arr, index)
findDup(arr, index, _index) #Has to remain same here, because length has changed now
def deletedup(arr, del_index):
del arr[del_index]
return arr
arr = [1, 2, 3, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7]
findDup(arr)
print arr

Categories

Resources