93

I want to display the product browsing history, so I am storing the product ids in a browser cookie.

Because the list of history is limited to 5 items, I convert the cookie value to an array, then check the length of it and cut the redundant.

The code below is what I have tried, but it does not work; the array item isn't removed.

I would like to ask how to limit the array length so it can only store 5 items?

Or

How can I cut the items after the array index 4?

var id = product_id;
var browseHistory = $.cookie('history');
if (browseHistory != null) {
  var old_cookie = $.cookie('history');
  var new_cookie = '';

  if (old_cookie.indexOf(',') != -1) {
    var arr = old_cookie.split(',');
    if (arr.length >= 5) {
      arr.splice(4, 1)
    }
  }

  new_cookie = id + ',' + old_cookie;
  $.cookie('history', new_cookie, { expires: 7, path: '/' });
} else {
  $.cookie('history', id, { expires: 7, path: '/' });
}
mshell_lauren
  • 5,171
  • 4
  • 28
  • 36
Charles Yeung
  • 38,347
  • 30
  • 90
  • 130
  • your splice looks fine, except you could do `arr.splice(4, arr.length - 4)` to make sure. are you saying the splice does not work or the cookie? you are setting new_cookie to old_cookie, which still contains 5+ items... – Rhumborl Jan 09 '13 at 13:46

8 Answers8

170

You're not using splice correctly:

arr.splice(4, 1)

this will remove 1 item at index 4. see here

I think you want to use slice:

arr.slice(0,5)

this will return elements in position 0 through 4.

This assumes all the rest of your code (cookies etc) works correctly

Matthias
  • 7,432
  • 6
  • 55
  • 88
Samuele Mattiuzzo
  • 10,760
  • 5
  • 39
  • 63
53

The fastest and simplest way is by setting the .length property to the desired length:

arr.length = 4;

This is also the desired way to reset/empty arrays:

arr.length = 0;

Caveat: setting this property can also make the array longer than it is: If its length is 2, running arr.length = 4 will add two undefined items to it. Perhaps add a condition:

if (arr.length > 4) arr.length = 4;

Alternatively:

arr.length = Math.min(arr.length, 4);
fregante
  • 29,050
  • 14
  • 119
  • 159
  • 1
    If you don't want to mutate the original array, it's better to clone it first with slice: `var clonedArray = arr.slice();` and then update the length of the newly cloned array. – Giorgio Tempesta Mar 13 '20 at 11:55
  • 3
    If you want a new array, just use `.slice(start, end)`, no need to _also_ set the `.length` – fregante Mar 14 '20 at 12:57
  • You’re right, I was so much focused on the risks of mutation that I forgot that the original purpose of slice is precisely this one! – Giorgio Tempesta Mar 15 '20 at 18:23
29
arr.length = Math.min(arr.length, 5)
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
justspamjustin
  • 1,730
  • 3
  • 19
  • 30
10
var  arrLength = arr.length;
if(arrLength > maxNumber){
    arr.splice( 0, arrLength - maxNumber);
}

This solution works better in a dynamic environment like p5js. I put this inside the draw call and it clamps the length of the array dynamically.

The problem with

arr.slice(0,5)

is that it only takes a fixed number of items off the array per draw frame, which won't be able to keep the array size constant if your user can add multiple items.

The problem with

if (arr.length > 4) arr.length = 4;

is that it takes items off the end of the array, so which won't cycle through the array if you are also adding to the end with push().

BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
Luche
  • 101
  • 1
  • 5
5

I think you could just do:

let array = [];
array.length = 2;
Object.defineProperty(array, 'length', {writable:false});


array[0] = 1 // [1, undefined]

array[1] = 2 // [1, 2]

array[2] = 3 // [1, 2] -> doesn't add anything and fails silently

array.push("something"); //but this throws an Uncaught TypeError
La Secta
  • 51
  • 1
  • 4
  • Have a look at [this](https://meta.stackexchange.com/questions/43019/how-do-comment-replies-work) – skillsmuggler Dec 21 '19 at 12:17
  • @skillsmuggler what do u think 'bout my first contribution to this site? are you agree on this solution? any disadvantages? if you know ? please tell me : tell me what is wrong then; cheers – La Secta Dec 22 '19 at 20:31
5

I was surprised nobody mentioned the following snippet to limit the length of the array:

arr.splice(5);

According to the Parameters definitions for splice, if start is larger than the length of the array, it will be set to the length of the array, and if deleteCount is omitted or larger than the array length, all of the items after start will be deleted.

Therefore, if you want to limit an array to some MAX_SIZE (modifying the existing array instead of creating a new instance) an easy shortcut is just arr.splice(MAX_SIZE).

As others have said, there is more going on with the code in the question, but given the title and spirit of the ask, I hope this is a useful answer for anyone else ending up here via search.

Note: According to the compatibility notes for IE 5.5-8, deleteCount does not work as described above, so this solution won't work right on those browsers.

dbudzins
  • 436
  • 5
  • 8
  • Worth noting that while `arr.splice(n)` will limit the array (and even `arr.splice(Infinity)` as a no-op), it does it in-place and splice's return is _not_ the limited list (as I thought for a good few minutes just now) – snazzybouche Mar 28 '23 at 09:14
1

You need to actually use the shortened array after you remove items from it. You are ignoring the shortened array.

You convert the cookie into an array. You reduce the length of the array and then you never use that shortened array. Instead, you just use the old cookie (the unshortened one).

You should convert the shortened array back to a string with .join(",") and then use it for the new cookie instead of using old_cookie which is not shortened.

You may also not be using .splice() correctly, but I don't know exactly what your objective is for shortening the array. You can read about the exact function of .splice() here.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

Came here but couldn't find a functional way of limiting the length of an array.

So I came up with:

const list = ["a","b","c","d","e","f","g","h","i"];
const listWithOnly3Items = list.filter((element,index) => index < 3);
Torben
  • 86
  • 5