Am un model, eventual cu mii de obiecte. Mă întrebam ce ar fi cel mai eficient mod de a le stoca și extrage un singur obiect o dată am l's id. Id-ul's sunt numere lungi.
Deci, acestea sunt cele 2 optiuni m-am gândit. în opțiunea one it's un simplu tablou cu o incrementarea indexului. în opțiunea 2-l's un tablou asociativ și, poate, un obiect, dacă nu se face o diferență. Intrebarea mea este care este cea mai eficientă, atunci când am cea mai mare nevoie de a primi un singur obiect, dar, de asemenea, uneori bucla prin și le sorta.
Opțiunea unu cu non tablou asociativ:
var a = [{id: 29938, name: 'name1'},
{id: 32994, name: 'name1'}];
function getObject(id) {
for (var i=0; i < a.length; i++) {
if (a[i].id == id)
return a[i];
}
}
Opțiunea doi cu tablou asociativ:
var a = []; // maybe {} makes a difference?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
return a[id];
}
Actualizare:
OK, am înțeles că, folosind o matrice în cea de-a doua opțiune este iese din discuție. Deci, declarația linia a doua opțiune ar trebui să fie într-adevăr: var a = {};
și singura întrebare este: ce are performanțe mai bune în recuperarea unui obiect cu un anumit id: o matrice sau un obiect în cazul în care id-ul este cheia.
și, de asemenea, va răspunde schimba, dacă nu va avea pentru a sorta lista de mai multe ori?
Versiunea scurtă: Tablouri sunt în mare parte mai repede decât obiecte. Dar nu există nici o 100% soluție corectă.
var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];
var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};
var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};
for (var f = 0; f < 2000; f++) {
var newNo = Math.floor(Math.random()*60000+10000);
if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
a1.push({id: newNo, name: 'test'});
}
Există unele idei preconcepute, în întrebarea dumneavoastră.
* Acestea sunt tablouri:**
var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";
Aceasta este o matrice, de asemenea:
var a3 = [];
a3[29938] = "a";
a3[32994] = "b";
L's de fapt o matrice cu găuri în ea, pentru că fiecare matrice are operatorul de indexare. L's mai lent decât tablouri fără găuri. Dar iterarea manual prin matrice este chiar mai lent (mai ales).
Acesta este un obiect:
var a3 = {};
a3[29938] = "a";
a3[32994] = "b";
Aici este un test de performanță de trei posibilități:
Un excelent citit despre aceste subiecte la Smashing Magazine: Scris rapid, eficient memoria JavaScript
L'nu e chiar o performanta întrebare, la toate, deoarece tablouri și obiecte de lucru foarte diferit (sau ar trebui, cel puțin). Tablouri au o continuă indicele 0..n
, în timp ce obiectele harta arbitrare cheile de la valori arbitrare. Dacă tu vrei să furnizeze anumite chei, singura alegere este un obiect. Dacă tu nu't grijă despre cheile, o matrice este.
Dacă încercați să setați arbitrare (numeric) tastele de pe o matrice, aveți într-adevăr o performanță pierdere, deoarece comportamental matrice va umple în toate indexurile între:
> foo = [];
[]
> foo[100] = 'a';
"a"
> foo
[undefined, undefined, undefined, ..., "a"]
(Rețineți că matrice nu de fapt conține 99 "nedefinit" valorile, dar se va comporta în acest fel, deoarece te're [trebuie să fie] iterarea matrice la un moment dat.)
De literali pentru ambele opțiuni ar trebui să fie foarte clar modul în care acestea pot fi utilizate:
var arr = ['foo', 'bar', 'baz']; // no keys, not even the option for it
var obj = { foo : 'bar', baz : 42 }; // associative by its very nature
Cu ES6 cele mai performante cum ar fi de a utiliza o Hartă.
var myMap = new Map();
myMap.set(1, 'myVal');
myMap.set(2, { catName: 'Meow', age: 3 });
myMap.get(1);
myMap.get(2);
Puteți utiliza caracteristici ES6 astăzi, folosind un shim (https://github.com/es-shims/es6-shim).
Performanța va varia în funcție de browser-ul și scenariu. Dar aici este un exemplu în cazul în care "Harta" este cel mai performant: https://jsperf.com/es6-map-vs-object-properties/2
REFERINȚĂ https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
În NodeJS dacă știți ID
, looping prin matrice este foarte lent în comparație cu obiectul[ID]`.
const uniqueString = require('unique-string');
const obj = {};
const arr = [];
var seeking;
//create data
for(var i=0;i<1000000;i++){
var getUnique = `${uniqueString()}`;
if(i===888555) seeking = getUnique;
arr.push(getUnique);
obj[getUnique] = true;
}
//retrieve item from array
console.time('arrTimer');
for(var x=0;x<arr.length;x++){
if(arr[x]===seeking){
console.log('Array result:');
console.timeEnd('arrTimer');
break;
}
}
//retrieve item from object
console.time('objTimer');
var hasKey = !!obj[seeking];
console.log('Object result:');
console.timeEnd('objTimer');
Și rezultatele:
Array result:
arrTimer: 12.857ms
Object result:
objTimer: 0.051ms
Chiar dacă cauta ID-ul este primul din matrice/obiect:
Array result:
arrTimer: 2.975ms
Object result:
objTimer: 0.068ms
Am încercat să fac acest lucru la următoarea dimensiune, literalmente.
A dat o a 2-dimensional matrice, în care axele x și y sunt întotdeauna de aceeași lungime, este mai rapid să:
a) să se uite în sus la mobil prin crearea unui tablou bidimensional și se uită în sus la primul indice, urmat de cel de-al doilea index, am.e:
var arr=[][]
var cell=[x][y]
sau
b) de a crea un obiect cu o reprezentare șir de coordonatele x și y, și apoi face o singură căutare pe care obj, am.e:
var obj={}
var cell = obj['x,y']
Rezultatul: Pare că-l's mult mai rapid pentru a face două index numeric căutări pe tablouri, decât o proprietate de căutare pe obiect.
Rezultatele aici:
Depinde de utilizare. Dacă cazul este în căutare de obiecte este foarte rapid.
Aici este un Plunker exemplu pentru a testa performanța de matrice și obiect de căutări.
https://plnkr.co/edit/n2expPWVmsdR3zmXvX4C?p=preview
Veți vedea că;
În căutarea pentru 5.000 articole în 5.000 lungimea matrice de colectare, preia 3000
milisecons
Cu toate acestea, în Căutarea pentru 5.000 articole în obiect a 5.000 proprietăți, să ia doar cu " 2 " sau " 3 " milisecons
De asemenea, face obiectul copac don't face o diferență enormă
Am avut o problema asemanatoare ca eu sunt cu care se confruntă în cazul în care am nevoie pentru a stoca live sfeșnice de la un eveniment sursă limitată la x elemente. Aș putea le-au depozitat într-un obiect, în cazul în care amprenta de timp de fiecare lumânare ar acționa ca o cheie și lumânarea în sine ar acționa ca valoare. O altă posibilitate a fost că am putut să-l stocați într-o matrice în care fiecare element a fost lumânarea în sine. O problemă despre live lumânări este că se păstrează trimiterea de actualizări de pe aceeași amprentă de timp în cazul în care cea mai recentă actualizare deține cele mai recente date, prin urmare, să fie actualizarea unui element existent sau adăuga unul nou. Deci, aici este un frumos de referință, care încearcă să combine toate cele 3 posibilități. Tablouri în soluția de mai jos sunt cel putin 4x mai rapid, în medie. Simțiți-vă liber pentru a juca
"use strict";
const EventEmitter = require("events");
let candleEmitter = new EventEmitter();
//Change this to set how fast the setInterval should run
const frequency = 1;
setInterval(() => {
// Take the current timestamp and round it down to the nearest second
let time = Math.floor(Date.now() / 1000) * 1000;
let open = Math.random();
let high = Math.random();
let low = Math.random();
let close = Math.random();
let baseVolume = Math.random();
let quoteVolume = Math.random();
//Clear the console everytime before printing fresh values
console.clear()
candleEmitter.emit("candle", {
symbol: "ABC:DEF",
time: time,
open: open,
high: high,
low: low,
close: close,
baseVolume: baseVolume,
quoteVolume: quoteVolume
});
}, frequency)
// Test 1 would involve storing the candle in an object
candleEmitter.on('candle', storeAsObject)
// Test 2 would involve storing the candle in an array
candleEmitter.on('candle', storeAsArray)
//Container for the object version of candles
let objectOhlc = {}
//Container for the array version of candles
let arrayOhlc = {}
//Store a max 30 candles and delete older ones
let limit = 30
function storeAsObject(candle) {
//measure the start time in nanoseconds
const hrtime1 = process.hrtime()
const start = hrtime1[0] * 1e9 + hrtime1[1]
const { symbol, time } = candle;
// Create the object structure to store the current symbol
if (typeof objectOhlc[symbol] === 'undefined') objectOhlc[symbol] = {}
// The timestamp of the latest candle is used as key with the pair to store this symbol
objectOhlc[symbol][time] = candle;
// Remove entries if we exceed the limit
const keys = Object.keys(objectOhlc[symbol]);
if (keys.length > limit) {
for (let i = 0; i < (keys.length - limit); i++) {
delete objectOhlc[symbol][keys[i]];
}
}
//measure the end time in nano seocnds
const hrtime2 = process.hrtime()
const end = hrtime2[0] * 1e9 + hrtime2[1]
console.log("Storing as objects", end - start, Object.keys(objectOhlc[symbol]).length)
}
function storeAsArray(candle) {
//measure the start time in nanoseconds
const hrtime1 = process.hrtime()
const start = hrtime1[0] * 1e9 + hrtime1[1]
const { symbol, time } = candle;
if (typeof arrayOhlc[symbol] === 'undefined') arrayOhlc[symbol] = []
//Get the bunch of candles currently stored
const candles = arrayOhlc[symbol];
//Get the last candle if available
const lastCandle = candles[candles.length - 1] || {};
// Add a new entry for the newly arrived candle if it has a different timestamp from the latest one we storeds
if (time !== lastCandle.time) {
candles.push(candle);
}
//If our newly arrived candle has the same timestamp as the last stored candle, update the last stored candle
else {
candles[candles.length - 1] = candle
}
if (candles.length > limit) {
candles.splice(0, candles.length - limit);
}
//measure the end time in nano seocnds
const hrtime2 = process.hrtime()
const end = hrtime2[0] * 1e9 + hrtime2[1]
console.log("Storing as array", end - start, arrayOhlc[symbol].length)
}
Concluzie 10 este limita aici
Storing as objects 4183 nanoseconds 10
Storing as array 373 nanoseconds 10
Dacă aveți un sortat apoi, puteți face o căutare binară și că este mult mai rapid decât un obiect de căutare, puteți vedea răspunsul meu aici: https://stackoverflow.com/questions/57422718/how-to-search-faster-in-a-sorted-array-using-javascript