অ্যারে বনাম। জাভাস্ক্রিপ্টে অবজেক্ট দক্ষতা


145

আমার কাছে সম্ভবত হাজার হাজার অবজেক্টের একটি মডেল রয়েছে। আমি ভাবছিলাম যে এগুলি সংরক্ষণ করার এবং কোনও একক বস্তুর আইডি হয়ে গেলে এটি পুনরুদ্ধার করার সবচেয়ে কার্যকর উপায় কী হবে? আইডি লম্বা সংখ্যা।

সুতরাং এই 2 টি বিকল্প সম্পর্কে আমি ভাবছিলাম। বিকল্প একটিতে এটি একটি ইনক্রিমেন্টিং সূচক সহ একটি সাধারণ অ্যারে। বিকল্প 2 এ এটি একটি সহযোগী অ্যারে এবং সম্ভবত কোনও বস্তু, যদি এটি কোনও পার্থক্য করে। আমার প্রশ্নটি কোনটি আরও দক্ষ, যখন আমার বেশিরভাগ ক্ষেত্রে একটি একক বস্তু পুনরুদ্ধার করা প্রয়োজন তবে মাঝে মধ্যে সেগুলি লুপ করেও বাছাই করে।

অ অ্যাসোসিয়েটিভ অ্যারে সহ একটি বিকল্প:

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];
    }
}

সহযোগী অ্যারে সহ দুটি বিকল্প:

var a = [];  // maybe {} makes a difference?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
    return a[id];
}

হালনাগাদ:

ঠিক আছে, আমি পেয়েছি যে দ্বিতীয় বিকল্পে একটি অ্যারের ব্যবহার করা প্রশ্নটির বাইরে। সুতরাং ডিক্লেয়ারেশন লাইন দ্বিতীয় বিকল্পটি সত্যই হওয়া উচিত: var a = {};এবং একমাত্র প্রশ্ন: প্রদত্ত আইডির সাহায্যে কোনও বস্তু পুনরুদ্ধারে আরও ভাল কী সম্পাদন করা হচ্ছে: একটি অ্যারে বা কোনও আইডি যেখানে মূল কী।

এবং এছাড়াও, উত্তরটি যদি আমার তালিকায় অনেক বার বাছাই করতে হয় তবে কি পরিবর্তন হবে?


1
এই :: হতে পারে সাহায্য করে stackoverflow.com/questions/13309464/...
সুধীর Bastakoti

আপনার কি সর্বদা বাছাই করা সংগ্রহের দরকার? যদি তা হয় তবে অ্যারের ব্যতীত অন্য কোনও বিকল্প নেই (যদিও বর্তমানে আপনার মতো সূচকগুলি ব্যবহার করা হচ্ছে না)।
জন

@ জন আসলে, আমি করি। "আপনি বর্তমানে যেমন করেন" এর অর্থ কী?
মোশে শাহাম

1
@ মোশিশাহাম: অ্যারেগুলিতে 0 থেকে শুরু হওয়া অবিচ্ছিন্ন সূচী থাকা উচিত you আপনি যদি অ্যারে ব্যবহার করেন তবে অন্য কিছু করবেন না।
জন

আমার ধারণা এই বেঞ্চমার্কটি আপনার প্রশ্নের প্রথম অংশটির জবাব দেবে: jsben.ch/#/Y9jDP
এসপেন নেটস্কেপ

উত্তর:


143

সংক্ষিপ্ত সংস্করণ: অ্যারেগুলি বস্তুর তুলনায় বেশিরভাগ দ্রুত। তবে কোনও 100% সঠিক সমাধান নেই।

আপডেট 2017 - পরীক্ষা এবং ফলাফল

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'});
}

পরীক্ষা সেটআপ পরীক্ষার ফলাফল

মূল পোস্ট - ব্যাখ্যা

আপনার প্রশ্নে কিছু ভুল ধারণা রয়েছে।

জাভাস্ক্রিপ্টে কোনও সহযোগী অ্যারে নেই। কেবল অ্যারে এবং অবজেক্টস।

এটি অ্যারেগুলি:

var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";

এটিও একটি অ্যারে:

var a3 = [];
a3[29938] = "a";
a3[32994] = "b";

এটি মূলত এটির মধ্যে গর্তযুক্ত একটি অ্যারে থাকে কারণ প্রতিটি অ্যারেটিতে ক্রমাগত সূচি থাকে। এটি গর্ত ছাড়াই অ্যারেগুলির চেয়ে ধীর। কিন্তু অ্যারের মাধ্যমে ম্যানুয়ালি পুনরাবৃত্তি করা আরও ধীর (বেশিরভাগ)।

এটি একটি বস্তু:

var a3 = {};
a3[29938] = "a";
a3[32994] = "b";

এখানে তিনটি সম্ভাবনার পারফরম্যান্স পরীক্ষা দেওয়া হল:

লুকআপ অ্যারে বনাম হোলি অ্যারে বনাম অবজেক্ট পারফরম্যান্স টেস্ট

স্মাগিং ম্যাগাজিনে এই বিষয়গুলি সম্পর্কে একটি দুর্দান্ত পঠন: দ্রুত মেমরির দক্ষ জাভাস্ক্রিপ্ট লেখা


1
@ মোশে এবং এর মাধ্যমে জাভাস্ক্রিপ্টে অভিনয় সম্পর্কে সমস্ত আলোচনা করা উচিত। : পি
ডিজেজ

9
এটি আপনার সাথে কাজ করা ডেটার ডেটা এবং আকারের উপর নির্ভর করে। খুব ছোট ডেটা সেট এবং ছোট অবজেক্ট অ্যারে দিয়ে আরও ভাল পারফর্ম করবে। যদি আপনার লুপিংয়ের কথা যদি কোনও বৃহত ডেটা সেটে থাকে যেখানে আপনি কোনও বস্তুটিকে মানচিত্র হিসাবে ব্যবহার করেন তবে কোনও বস্তু আরও দক্ষ। jsperf.com/array-vs-object-performance/35
f1v

5
F1v সাথে একমত, কিন্তু পরিবর্ধন ও পরিবর্তন 35 পরীক্ষা একটি ত্রুটি রয়েছে: if (a1[i].id = id) result = a1[i];হওয়া উচিত: if (a1[i].id === id) result = a1[i];টেস্ট http://jsperf.com/array-vs-object-performance/37 কারেক্টস যে
চার্লস বার্ন

1
Http://jsperf.com/array-vs-object-performance/71 দেখুন । 5000 এর তুলনায় প্রায় 93 টি অবজেক্টের ডেটার একটি ছোট উপসেট রয়েছে (আমার ডেটা তৈরির জন্য লুপ করা উচিত ছিল, তবে আমি অ্যারেতে গর্ত চাইছিলাম) uter আমি পাশাপাশি একটি অনুপস্থিত আইডি যুক্ত করেছি যাতে অ্যারে লুকআপে সমস্ত উপাদান অতিক্রম করতে হয়। হোলি অ্যারে, কী দ্বারা অবজেক্ট, তারপরে ম্যানুয়াল অ্যারে। সুতরাং f1v হিসাবে বলা হয়েছে এটি সত্যই ডেটা মাপের উপর নির্ভর করে এবং যেখানে ম্যানুয়াল অ্যারে অনুসন্ধানের জন্য ডেটা রয়েছে।
চার্লস বাইর্ন

4
এই উত্তরটি এখানে এই পোস্টে জেএসফিউর সিদ্ধান্তগুলি সংক্ষিপ্ত করে আরও উন্নত করা যায় - বিশেষত যেহেতু জেএসফিউর ফলাফলই প্রশ্নের আসল উত্তর। বাকিগুলি অতিরিক্ত। যখন jscreen ডাউন হয় (যেমন এখনই) তখন এটি আরও প্রাসঙ্গিক। meta.stackexchange.com/questions/8231/…
জেফ

23

এটি মোটেও কার্য সম্পাদনের প্রশ্ন নয়, যেহেতু অ্যারে এবং অবজেক্টগুলি খুব আলাদাভাবে কাজ করে (বা ধারণা করা হয়, কমপক্ষে)। অ্যারেগুলির একটি অবিচ্ছিন্ন সূচক থাকে 0..n, যখন বস্তুগুলি স্বেচ্ছাচারিত মানগুলি স্বেচ্ছাচারিত মানগুলিতে মানচিত্র করে। আপনি যদি নির্দিষ্ট কী সরবরাহ করতে চান তবে একমাত্র পছন্দ হ'ল একটি অবজেক্ট। আপনি যদি কীগুলি সম্পর্কে চিন্তা না করেন তবে এটি একটি অ্যারে।

যদি আপনি কোনও অ্যারেতে স্বেচ্ছাসেবী (সংখ্যাসমূহ) কীগুলি সেট করার চেষ্টা করেন তবে আপনার সত্যিকার অর্থে একটি পারফরম্যান্স হ্রাস হয়েছে , কারণ আচরণগতভাবে অ্যারেটি সমস্ত সূচকগুলি এর মধ্যে পূরণ করবে:

> foo = [];
  []
> foo[100] = 'a';
  "a"
> foo
  [undefined, undefined, undefined, ..., "a"]

(দ্রষ্টব্য যে অ্যারেতে আসলে 99 টি undefinedমান নেই, তবে এটি এমনভাবে আচরণ করবে যেহেতু আপনি [অনুমান করা হচ্ছে] কোনও বিন্যাসে অ্যারেটি পুনরাবৃত্তি করবেন।)

উভয় বিকল্পের জন্য আক্ষরিকাগুলি এটিকে কীভাবে ব্যবহার করা যায় তা খুব পরিষ্কার করে দেওয়া উচিত:

var arr = ['foo', 'bar', 'baz'];     // no keys, not even the option for it
var obj = { foo : 'bar', baz : 42 }; // associative by its very nature

আমি নির্দিষ্ট কী সরবরাহ করতে চাই না। আমি কী আরও ভাল পারফরম্যান্স করছে তা জানতে চাই এবং আমি এটি নিয়ে কাজ করব। ঠিক আছে, সুতরাং দ্বিতীয় বিকল্পে একটি অ্যারের প্রশ্নের বাইরে রয়েছে। তবে একটি মিশ্রণ বিন্যাসের বিরুদ্ধে কোনও বস্তুর কী হবে?
মোশে শাহাম

1
@ মোশে জাভাস্ক্রিপ্টে অ-অ্যাসোসিয়েটিভ অ্যারের মতো জিনিস নেই। যদি আপনার কী (সংখ্যা বা স্ট্রিং) প্রয়োজন হয় তবে একটি অবজেক্ট ব্যবহার করুন। আপনার যদি কেবলমাত্র (আদেশযুক্ত) তালিকার প্রয়োজন হয় তবে অ্যারে ব্যবহার করুন। সময়কাল। পারফরম্যান্স আলোচনায় প্রবেশ করে না। যদি পারফরম্যান্স অত্যন্ত গুরুত্বপূর্ণ এবং আপনি আপনার কীগুলির সাথে যেভাবেই বাঁচতে পারেন তবে কোনটি আপনার পক্ষে আরও ভাল কাজ করে তা চেষ্টা করুন।
ছদ্মবেশ

5
তবে আমি কীটি আরও ভালভাবে সম্পাদন করছে তা জানতে চাই: একটি অ্যারের থেকে কোনও বস্তু পুনরুদ্ধার করা (এটির মধ্য দিয়ে লুপিং করে) বা আইডিটি মূল কী এমন একটি "সহযোগী" বস্তু থেকে। আমার প্রশ্নটি পরিষ্কার না হলে আমি দুঃখিত ...
মোশে শাহম

2
@ মোশে আপনি যদি কোনও কি বা কোনও বস্তু বা অ্যারেতে অ্যাক্সেস করেন তবে আপনি যা চান তা আবিষ্কার করার চেষ্টা করে কনটেইনারটি লুপিংয়ের চেয়ে সর্বদা অসীম দ্রুত হতে চলেছে। কোন অ্যারে বা কোনও অবজেক্টে কী দ্বারা কোনও আইটেম অ্যাক্সেস করার পার্থক্য সম্ভবত নগণ্য। লুপিং উভয় উপায়ে সম্ভবত খারাপ।
ছদ্মবেশ

1
@ ডিজেজ - কীভাবে "অ্যারে হোল্ডিং ব্যবহারকারী অবজেক্ট সম্পর্কে এবং ব্যবহারকারীর অবজেক্টটি পেতে, user_id" বনাম "অবজেক্টের কী user_idব্যবহার করে অবজেক্টের উপর ভিত্তি করে ইউজার অবজেক্ট পাওয়ার জন্য একটি লুপের প্রয়োজন যেহেতু কী হিসাবে ইউজার অবজেক্ট অ্যাক্সেস করা যায় user_id"? পারফরম্যান্সের দিক থেকে কোনটি ভালো? এ সম্পর্কে কোনও পরামর্শ প্রশংসা করা হয় :)
রেয়ন

13

ES6 এর সাথে সর্বাধিক পারফর্মেন্ট উপায় হ'ল মানচিত্রটি ব্যবহার করা।

var myMap = new Map();

myMap.set(1, 'myVal');
myMap.set(2, { catName: 'Meow', age: 3 });

myMap.get(1);
myMap.get(2);

আপনি আজ শিম ( https://github.com/es-shims/es6-shim ) ব্যবহার করে ES6 বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন ।

পারফরম্যান্স ব্রাউজার এবং দৃশ্যের উপর নির্ভর করে পরিবর্তিত হবে। তবে এখানে একটি উদাহরণ যেখানে Mapসর্বাধিক অভিনয় রয়েছে: https://jsperf.com/es6-map-vs-object-properties/2


রেফারেন্স https://developer.mozilla.org/en/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস / মানচিত্র


11
এটি ব্যাক আপ করার জন্য কোনও সংস্থান আছে? আমার পর্যবেক্ষণ থেকে এখন পর্যন্ত ES6 সেটগুলি অ্যারেগুলির চেয়ে দ্রুততর তবে ES6 মানচিত্র উভয় বস্তু এবং অ্যারেগুলির চেয়ে ধীর
স্টিল ব্রেন

1
এটি আরও বেশি "শব্দার্থক", আরও পারফরম্যান্ট নয়, যা ছিল প্রশ্ন।
অ্যালেক্সজি 9

3
@ অ্যালেক্সজি বেশ নিশ্চিত যে শিরোনামটি পরিষ্কারভাবে জানিয়েছে efficiency
কিউস - মোনিকা

@ কিক্স হ্যাঁ, আমার খারাপ: ও
অ্যালেক্সজি

8

ইন NodeJS আপনি কি জানেন যদি ID, এরে মাধ্যমে looping খুব ধীর সাথে তুলনা করা হয় object[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');

এবং ফলাফল:

Array result:
arrTimer: 12.857ms
Object result:
objTimer: 0.051ms

সন্ধানী আইডি অ্যারে / অবজেক্টের মধ্যে প্রথমটি হলেও:

Array result:
arrTimer: 2.975ms
Object result:
objTimer: 0.068ms

5

আমি এটি আক্ষরিকভাবে পরবর্তী মাত্রায় নিয়ে যাওয়ার চেষ্টা করেছি।

একটি 2 মাত্রিক অ্যারে দেওয়া হয়েছে, যেখানে x এবং y অক্ষ সবসময় একই দৈর্ঘ্যের হয়, এটি কি আরও দ্রুত:

ক) দ্বিমাত্রিক অ্যারে তৈরি করে প্রথম সূচীটি অনুসন্ধানের পরে দ্বিতীয় সূচীটি অনুসন্ধান করে সেলটি সন্ধান করুন, যেমন:

var arr=[][]    
var cell=[x][y]    

অথবা

খ) x এবং y স্থানাঙ্কগুলির একটি স্ট্রিং প্রতিনিধিত্ব করে একটি অবজেক্ট তৈরি করুন এবং তারপরে objজেজে একক অনুসন্ধান করুন, অর্থাত:

var obj={}    
var cell = obj['x,y']    

ফলাফল:
দেখা যাচ্ছে যে বস্তুর উপরে একাধিক সম্পত্তি অনুসন্ধানের চেয়ে অ্যারেগুলিতে দুটি সংখ্যার সূচক লক্কুয়ালগুলি করা আরও দ্রুত।

ফলাফল এখানে:

http://jsperf.com/arr-vs-obj-lookup-2


3

এটি ব্যবহারের উপর নির্ভর করে। যদি কেস লুকে দেখা হয় তবে খুব দ্রুত objects

অ্যারে এবং অবজেক্ট লুকআপের পারফরম্যান্স পরীক্ষা করার জন্য এখানে একটি প্লঙ্কার উদাহরণ।

https://plnkr.co/edit/n2expPWVmsdR3zmXvX4C?p=preview

আপনি এটি দেখতে পাবেন; জন্য খোঁজা হচ্ছে 5.000 আইটেম 5.000 দৈর্ঘ্য অ্যারের সংগ্রহ, নিতে 3000milisecons

তবে অবজেক্টে 5.000 আইটেমের সন্ধানে 5000 টি বৈশিষ্ট্য রয়েছে, কেবল 2বা 3মিলিসেকন নিন take

এছাড়াও অবজেক্ট ট্রি তৈরি করা বড় পার্থক্য রাখে না


0

আমার একই ধরণের সমস্যা হয়েছিল যার মুখোমুখি হচ্ছি যেখানে এক্স আইটেমের মধ্যে সীমাবদ্ধ ইভেন্ট উত্স থেকে আমার লাইভ ক্যান্ডেলস্টিকগুলি সঞ্চয় করতে হবে। আমি এগুলিকে এমন কোনও বস্তুতে রাখতে পারি যেখানে প্রতিটি মোমবাতির টাইমস্ট্যাম্প কী হিসাবে কাজ করবে এবং মোমবাতি নিজেই মান হিসাবে কাজ করবে। আরেকটি সম্ভাবনা ছিল যে আমি এটিকে এমন একটি অ্যারেতে রাখতে পারি যেখানে প্রতিটি আইটেমটি নিজেই মোমবাতি ছিল। লাইভ মোমবাতি সম্পর্কে একটি সমস্যা হ'ল তারা একই টাইমস্ট্যাম্পে আপডেটগুলি প্রেরণ করা চালিয়ে যায় যেখানে সর্বশেষতম আপডেটটি সর্বাধিক সাম্প্রতিক ডেটা ধারণ করে তাই আপনি হয় কোনও বিদ্যমান আইটেম আপডেট করুন বা একটি নতুন যুক্ত করুন। সুতরাং এখানে একটি দুর্দান্ত বেঞ্চমার্ক যা সমস্ত 3 টি সম্ভাবনার সাথে একত্রিত করার চেষ্টা করে। নীচের সমাধানে অ্যারেগুলি গড়ে কমপক্ষে 4x দ্রুত হয়। খেলতে নির্দ্বিধায়

"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)
}

উপসংহার 10 এখানে সীমা

Storing as objects 4183 nanoseconds 10
Storing as array 373 nanoseconds 10

0

যদি আপনার বাছাই করা অ্যারে থাকে তবে আপনি বাইনারি অনুসন্ধান করতে পারেন এবং এটি কোনও অবজেক্ট দেখার চেয়ে দ্রুত, আপনি আমার উত্তরটি এখানে দেখতে পারেন:
জাভাস্ক্রিপ্ট ব্যবহার করে বাছাই করা অ্যারেতে কীভাবে দ্রুত অনুসন্ধান করতে হয়

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.