There are several modes when checking equality, Abstact (==)
, Strict (===)
, Same Value Zero
, Same Value (Object.is)
and some others like node
s deepEqual
. Each will give you different results, depending on your values. I will go with Strict equality as that is what you have used.
You have tagged the question ES6, so I will go with that and I am going to use the iterator feature.
I notice that you wish to keep the array the same length as the original, even if the supplied item is prepended to the array. You also speak like scaling is going to be an issue, so I will add some tests that will use a reasonably large data set.
var arr = [
{v: 1},
{v: 2},
{v: 3},
{v: 4},
];
// using iterators
function update(e) {
const length = arr.length;
const it = arr.entries();
let item = it.next();
while (!item.done) {
if (item.value[1].v === e.v) {
if (item.value[0] === 0) {
return;
}
e = arr.splice(item.value[0], 1)[0];
break;
}
item = it.next();
}
arr.unshift(e);
arr.length = length;
}
update({v: 1});
update({v: 2});
update({v: 6});
console.log(arr);
And here are some tests.
const Darr = [];
for (let x = 0; x < 100000; x += 1) {
Darr.push({v: x});
}
console.log('Original array length: ', Darr.length);
let arr;
function test(fn) {
arr = Darr.slice();
let count = 1000;
const Ts = performance.now();
while (count) {
fn({v: 1});
fn({v: 2});
fn({v: 10000001});
count -= 1;
}
const Te = performance.now();
console.log(`name: ${fn.name} time: ${Math.ceil(Te - Ts)} items: ${arr.length}`);
}
// code from your question
function update(e) {
var i = arr.findIndex(o => o.v === e.v);
if (i === 0) return;
if (i > 0) arr = [e].concat(arr.slice(0, i), arr.slice(i+1));
if (i < 0) arr = [e].concat(arr.slice(0, arr.length - 1)); // keep the array has 4 elements
}
test(update);
// using iterators
function update1(e) {
const length = arr.length;
const it = arr.entries();
let item = it.next();
while (!item.done) {
if (item.value[1].v === e.v) {
if (item.value[0] === 0) {
return;
}
e = arr.splice(item.value[0], 1)[0];
break;
}
item = it.next();
}
arr.unshift(e);
arr.length = length;
}
test(update1);
// other answers
function update2(e) {
// find index
var i = arr.findIndex(o => o.v === e.v);
// if already at start, nothing to do
if (i === 0) return;
// remove old occurrency, if existing
if (i > 0) {
arr.splice( i, 1 );
}
// add e to the start
arr.unshift( e );
// keep array at the correct size
arr.length = Math.min( arr.length, 4 );
}
test(update2);
const update3 = (e) => { var i = arr.findIndex(o => o.v === e.v);
i > 0 ? arr.splice(0,0,arr.splice(i,1)[0])
: i && arr.splice(0,0,e);
(arr.length > 5) && arr.length--
return arr;
};
test(update3);