This question already has answers here:
Remove items from array with splice in for loop [duplicate]
(5 answers)
Closed 2 years ago.
I have the following array
var array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]]
Which i want to end looking like:
[["noteremove",1],[10],["notremove",1]]
Meaning that all [0] should be purged.
I have this, but it doesnt work:
function arraysEqual(a1,a2) {
return JSON.stringify(a1)==JSON.stringify(a2);
}
var array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]]
for (let i = 0; i< array.length;i++){
if(arraysEqual(array[i],[0])){
console.log("its equal")
array.splice(i,1)
}
}
console.log(array); //It logs
//[ [ 0 ], [ 'noteremove', 1 ], [ 10 ], [ 'notremove', 1 ] ]
//The initial 0 shouldnt be there
You could use filter method and check if length is 1 and first element is 0.
var array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]]
var result = array.filter(e => !(e.length == 1 && e[0] === 0))
console.log(result)
A simple loop should get the work done:
let array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]]
let new_array = []
array.forEach(function(element){
if(JSON.stringify(element)!=JSON.stringify([0])){
new_array.push(element)
}
})
console.log(new_array)
I'm using here stringify to compare both arrays, although, there are other methods
Using .splice() within your an incrementing for loop will shift the indexes of all values once a value is removed, causing you to miss some values. If you loop through the array backwards then removing elements won't shift the values to lower indexes, allowing you to remove all matches:
function arraysEqual(a1, a2) {
return JSON.stringify(a1) === JSON.stringify(a2);
}
var array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]];
for (let i = array.length-1; i >= 0; i--) {
if (arraysEqual(array[i], [0])) {
array.splice(i, 1)
}
}
console.log(array);
Instead, an easier approach would be to use .filter(), where you can provide a callback function which gets call on each element in your array. If the callback returns true the item is kept, if it returns false the item is removed from the new array:
const array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]];
const res = array.filter(arr => arr.length !== 1 || arr[0] !== 0);
console.log(res);
You can try this-
var array = [[0],[0],[0],["noteremove",1],[10],["notremove",1]]
const result = [];
array.forEach(v => {
if (v.length === 1 && v[0] === 0) {
// Do nothing
} else {
result.push(v)
}
});
console.log(result);
Related
This question already has answers here:
Looping through array and removing items, without breaking for loop
(17 answers)
Closed 1 year ago.
I just did a coding challenge where I had to remove all non numberic items from an array without creating a new array which means no map or filter.
I didn't do that great because I was trying to splice but I'd lose my index.
What is a nice way of doing this?
const filterNums = (nums) => {
for (let item in nums) {
if (typeof nums[item] !== 'number') {
// Remove item
}
}
return nums;
};
console.log(filterNums([1, 'a', 2, 'b', true]));
Use an indexed-based loop instead, starting at the end of the array.
const filterNums = (nums) => {
for (let i = nums.length - 1; i >= 0; i--) {
if (typeof nums[i] !== 'number') {
nums.splice(i, 1);
}
}
return nums;
};
console.log(filterNums([1, 'a', 2, 'b', true]));
const filterData = apiData.filter(data => {
return this.shouldDisplayItem(
data,
[this.state.searchValue],
this.state.filterKeyValue
);
}).filter(i => i.vid),
x = 0,
y = apiData.map(i => i.vid).indexOf(markerId);
A[x] = A.splice(y, 1, A[x])[0];
For example, I have an array = [0,1,2,3,4,5,6,7,8,9]. First I want to filter value greater than 2 then I want to swap 7 and 8 via index number.
In the original project at first, I am doing some filter than on the second filter I am swapping two array object
can we filter two times same array in a single go?
You can use filter to filter out the array and then swap using the prototype
Array.prototype.swap = function (swapFirst,swapSecond) {
var x = this.findIndex(a=> a === swapFirst);
var y = this.findIndex(a=> a === swapSecond);
var b = this[y];
this[y] = this[x];
this[x] = b;
return this;
}
var apiData = [0,1,2,3,4,5,6,7,8,9];
var filtered= apiData.filter(a=> a > 2).swap(7,8);
console.log(filtered);
You can do it simple with reduce()
So here in reduce function i am first checking for value > 2 condition.
if it passes than i am checking for value === 7 or value===8 if any of them matches i change the value as you wanted.if not i just directly push into output array.
if value > 2 fails i don't push that value in output array.
let arr = [0,1,2,3,4,5,6,7,8,9];
let op = arr.reduce((op,cur)=>{
if(cur>2){
if( cur ===7)op.push(8);
else if(cur === 8) op .push(7);
else op.push(cur);
}
return op;
},[])
console.log(op);
than on the second filter I am swapping two array object
Array.prototype.filter should only filter elements from the array, not map / swap elements.
can we filter two times same array in a single go?
Yes, for example:
[1, 2, 3, 4, 5].filter((e, idx) => e + 1 === idx).filter(e => e%2 === 0)
can be replaced with:
[1, 2, 3, 4, 5].filter((e, idx) => e + 1 === idx && e%2 === 0)
I have searched on here and have not found a solution. Obviously I will be corrected if I am wrong. What I am trying to do is return values that do not have a duplicates in an array.
Examples:
myArr = [2,1,2,3] // answer [1,3]
myArr = [3,1,2,2,3] // answer [1]
I would post some code but I have not been able to figure this out myself and the only code examples I have found are for removing any duplicate values.
The possible solution above is to return no duplicates... I am trying to return values that are don't have duplicates.
One option is to use the optional second argument to indexOf to find duplicate indexes. Consider that for a given element e and an index i:
if e is the first of two identical elements in the array, indexOf(e) will return i and indexOf(e, i + 1) will return the index of the second element.
if e is the second of two identical elements in the array, indexOf(e) will return the index of the first element, and indexOf(e, i + 1) will return -1
if e is a unique element, indexOf(e) will return i and indexOf(e, i + 1) will return -1.
Therefore:
myArr.filter(function (e, i, a) {
return a.indexOf(e) === i && a.indexOf(e, i + 1) === -1
});
var isUnique = function(v,i,arr){
// return true if the first occurrence is the last occurrence
return ( arr.indexOf(v) === arr.lastIndexOf(v) );
};
var uniqueVals = myArr.filter(isUnique);
console.log( uniqueVals );
If is not an associative array (your case):
var myArr = [1,2,2,3,4,4,1,5];
var myNewArr = [];
if (myArr.length > 0 )
{
myNewArr[0] = myArr[myArr.length-1];
}
var count = 1;
myArr.sort();
for (var i = myArr.length - 2; i >= 0; i--) {
if(myArr[i] != myArr[i-1])
{
myNewArr[count] = myArr[i];
count++;
}
}
var yourArray = [1, 2, 1, 3];
var uniqueValues = [];
$.each(yourArray, function (i, value) { //taking each 'value' from yourArray[]
if ($.inArray(value, uniqueValues) === -1) {
uniqueValues.push(value); // Pushing the non - duplicate value into the uniqueValues[]
}
});
console.log(uniqueValues);
Result: [1,2,3];
I'm trying to create a function that puts each array element in its own array, recursively.
I think my base case is correct, but my recursive call doesn't appear to be working. any insight?
function ownList(arr){
if (arr.length === 1) {
arr[0] = [arr[0]];
return;
} else {
return arr[0].concat(ownList(arr.slice(1)));
}
}
var arr = [1,2,3]
console.log(ownList(arr))// returns []
//should return [[1],[2],[3]]
Here I'm trying to put each pair in it's own list (recursive only). This code below is correct (update)
function ownListPair(arr){
if (arr.length === 0)
return arr;
else if(arr.length === 1)
return [[arr[0], 0]];
else
return [[arr[0], arr[1]]].concat(ownListPair(arr.slice(2)));
}
// var arr = [3,6,8,1,5]
var arr = [2,7,8,3,1,4]
//returns [ [ 2, 7 ], [ 8, 3 ], [ 1, 4 ]]
console.log(ownListPair(arr))
I prefer this solution for several reasons:
function ownList(a) {
return a.length == 0
? []
: [[a[0]]].concat(ownList(a.slice(1)))
}
It's shorter and more concise
It works for empty arrays as well
The actual wrapping happens only once in the last line. Treating length == 1 separately -- as suggested by others -- is not necessary.
It would more appropriate to make a length of 0 be the null case. Then you just have to get the brackets right. The thing on the left side of the concat should be an array consisting of the array containing the first element.
function ownList(arr) {
return arr.length ? [[arr[0]]].concat(ownList(arr.slice(1))) : [];
}
Here's an alternative, take your pick:
function ownList(arr) {
return arr.length ? [[arr.shift()]] . concat(ownList(arr)) : [];
}
Using a bit of ES6 magic for readability:
function ownList([head, ...tail]) {
return head === undefined ? [] : [[head]] . concat(ownList(tail));
}
Here the [head, ...tail] is using parameter destructuring which pulls the argument apart into its first element (head) and an array of remaining ones (tail).
Instead of concat you could also use the array constructor:
function ownList([head, ...tail]) {
return head === undefined ? [] : Array([head], ...ownList(tail));
}
I think your basic assumption is wrong. What you need to do is check if each item in the array is an array, if not just add the item to the new array, if so have the function run itself on the array item.
That is recursion.
This code does that kind of recursion...
function ownList(arr)
{
var newArr = [];
var length = arr.length;
for (var i = 0; i < length; i++) {
if (typeof(arr[i]) === 'object') {
newArr.push(ownList(arr[i]));
continue;
}
newArr.push([arr[i]]);
}
return newArr;
}
var arr = [1, 2, 3];
console.log(ownList(arr));
Would something like this work:
var arr = [1, 2, 3, ["a", "b", "c", ["str"]]],
result = [];
function flatten(input){
input.forEach(function(el){
if(Array.isArray(el)){
flatten(el)
}else{
result.push([el]);
}
});
}
flatten(arr);
console.log(JSON.stringify(result));
//[[1],[2],[3],["a"],["b"],["c"],["str"]]
JSBIN
Edit:
var result = [];
function flatten(input){
if (input.length === 0){
console.log( "result", result ); //[[1],[2],[3],["a"],["b"],["c"],["str"]]
return;
}
//if zeroth el of input !array, push to result
if (!Array.isArray(input[0])){
result.push(input.splice(0, 1));
flatten(input);
}else{
flatten(input[0]); //else, give input[0] back to flatten
}
}
window.onload = function(){
var arr = [1, 2, 3, ["a", "b", "c", ["str"]]];
flatten(arr);
}
JSBIN
After struggling through this today, turns out that this works :)
function ownList(arr){
//base case:
if (arr.length === 1) {
return [arr];
}
//recurse
//have to do two brackets here --> (arr.slice(0,1)) since length > 1
return [arr.slice(0,1)].concat(ownList(arr.slice(1)));
}
var arr = [1,2,3]
console.log(ownList(arr))// returns [[1],[2],[3]]
I would like to cache some data in javascript, but the cache should be limited to 10 elements for example.
I can place the objects in javascript array, but what is the best way to keep the array limited to 10 elements?
Example:
function getData(dataId) { return new NextDataObject(dataId); }
var array = new Array();
array.push(getData(0));
array.push(getData(1));
(...)
array.push(getData(10)); // this should result in dropping "oldest" data, so getData(0) should be removed from the array, so that in array there are only 10 objects at maximum
Should such mechanism be written manually (using splice() for example?) or are there better ways to achieve such "cache" structure in javascript?
BTW: in this particular situation I'm using angular.
Override the push function of your caching array.
var array = new Array()
array.push = function (){
if (this.length >= 10) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
Plunker
To make this more reusable I created a method which returns new instance of such array (basing on above code).
function getArrayWithLimitedLength(length) {
var array = new Array();
array.push = function () {
if (this.length >= length) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
return array;
}
var array = getArrayWithLimitedLength(10);
To remove first element from array use shift:
if (arr.length > 10) {
arr.shift(); // removes the first element from an array
}
How about this object?
function Cache(maxLength) {
this.values = [];
this.store = function(data) {
if(this.values.length >= maxLength) {
this.getLast();
}
return this.values.push(data);
}
this.getLast = function() {
return this.values.splice(0,1)[0];
}
}
cache = new Cache(3);
// => Cache {values: Array[0]}
cache.store(1)
// => 1
cache.store(2)
// =>2
cache.store(3)
// => 3
cache.store(4)
// =>3
cache.values
// => [2, 3, 4]
cache.getLast()
// => 2
cache.values
[3, 4]
You could create new method in Array.prototype to mimic your needs.
Array.prototype.push_with_limit = function(element, limit){
var limit = limit || 10;
var length = this.length;
if( length == limit ){
this.shift();
}
this.push(element);
}
var arr = []
arr.push_with_limit(4); // [4]
arr.push_with_limit(9); // [4, 9]
....
// 11th element
arr.push_with_limit(3); // [9, ..., 3] 10 elements
Simple fixed length queue:
Array.prototype.qpush = function( vals, fixed ) {
if (arguments.length) {
if (Array.isArray(vals)) {
for (var v of vals) {
this.push(v);
}
} else {
this.push(vals);
}
var _f = (typeof this.fixed != undefined) ? this.fixed : 0;
if (typeof fixed != undefined) {
_f = (Number(fixed)===fixed && fixed%1===0 ) ? fixed : _f;
}
this.fixed = _f;
if (this.fixed>0) this.splice(0, this.length - _f);
}
}
var q = new Array();
q.push(0);
q.qpush( [1, 2, 3], 10 );
q.qpush( [4] );
q.qpush( 5 );
q.qpush( [6, 7, 8, 9, 10, {k:"object"} ] );
console.log(q);
if(array.length == 10) {
array.splice(0, 1);
// this will delete first element in array
}
If you do a check whether the array has reached 10 entries with array.length, just remove the first element before pushing a new element. This can be done several ways as Tushar states, array.shift() would be the fastest, but you can indeed use array.splice() aswell.
It would look like this:
if(array.length > 10) {
array.shift();
array.push(getData(10));
}
On a side note, instead of using var array = new Array() I suggest you simply use var array = [];. This is because the new keyword in Javascript sometimes has bad side effects. If you for example want to create an array with 1 element being a digit, and you use var arr = new Array(12);, an array with 12 undefined elements will be created. Whereas var arr = [12]; will create an array with 1 element, the digit 12.
But I guess that's a minor thing to consider..
You could use an object instead...
var obj = {}; //your cache object
obj[window.performance.now()] = getData(val); //add value, index by microsecond timestamp
if(Object.keys(obj).length > 10){ // then if the length ever gets bigger than 10..
var array = Object.keys(obj).sort(); //sort the properties by microsecond asc
delete obj[array[0]]; //delete the oldest one
}
Here is a jsFiddle example showing how it works: https://jsfiddle.net/uhkvk4mw/
just check if the length is reached then pop it
if(arr.length > someNumber){
arr.pop(); // pop() will remove the last element
}