এর চেয়ে বড় / কম-এর জন্য স্টেটমেন্ট স্যুইচ করুন


230

সুতরাং আমি এই মত একটি সুইচ বিবৃতি ব্যবহার করতে চান:

switch (scrollLeft) {
  case (<1000):
   //do stuff
   break;
  case (>1000 && <2000):
   //do stuff
   break;
}

এখন আমি জানি যে এই বিবৃতিগুলির ( <1000) বা ( >1000 && <2000) কোনওটিই কাজ করবে না (বিভিন্ন কারণে, স্পষ্টতই)। আমি যা বলছি তা হ'ল সবচেয়ে দক্ষ উপায়। আমি 30 টি ifস্টেটমেন্ট ব্যবহার করে ঘৃণা করি , তাই আমি স্যুইচ সিনট্যাক্সটি ব্যবহার করব। আমি কি কিছু করতে পারি?


5
আপনার পদক্ষেপগুলি কি নিয়মিত হয়? আমি বলতে চাচ্ছি, আপনি যদি 1000 দ্বারা scrollLeft ভাগ, আপনি সুইচ করতে পারেন 1, 2, 3 ...
IcanDivideBy0

হতে পারে আপনি একটি বাছাই করা অ্যারে তৈরি করতে পারেন যা সম্পর্কিত ক্রিয়াকলাপের সাথে শর্ত পরিসীমা মানচিত্র করে এবং এটিতে বাইনারি অনুসন্ধান প্রয়োগ করে। বা যদি আপনার শর্তগুলি পর্যাপ্ত নিয়মিত হয় তবে আপনি সরাসরি কল করতে পারেন your_mapper_object[scrollLeft / SOME_CONST], ধরে নেওয়া your_mapper_objectএমন কিছু {1: some_func, 2: another_func, ...}। এবং এই ক্ষেত্রে আপনি স্যুইচও ব্যবহার করতে পারেন।
জিয়াং

উত্তর:


731

আমি যখন অন্যান্য উত্তরের সমাধানগুলির দিকে তাকালাম তখন আমি এমন কিছু জিনিস দেখেছি যা আমি জানি যা পারফরম্যান্সের জন্য খারাপ। আমি তাদের একটি মন্তব্যে রাখতে যাচ্ছিলাম তবে আমি মনে করি এটির বেঞ্চমার্ক করা এবং ফলাফলগুলি ভাগ করে নেওয়া ভাল। আপনি নিজে এটি পরীক্ষা করতে পারেন । নীচে প্রতিটি ফলাফল (ymmv) প্রতিটি ব্রাউজারে দ্রুত অপারেশন করার পরে স্বাভাবিক করা হয়েছে (এমএসে পরম সময় পেতে স্বাভাবিক মানের সাথে 1.0 বারটি গুণ করুন)।

                    ক্রোম ফায়ারফক্স অপেরা এমএসআইই সাফারি নোড
-------------------------------------------------- -----------------
1.0 সময় 37ms 73ms 68ms 184ms 73ms 21ms
যদি-তাত্ক্ষণিক 1.0 1.0 1.0 2.6 1.0 1.0
if-indirect 1.2 1.8 3.3 3.8 2.6 1.0
সুইচ-তাত্ক্ষণিক 2.0 1.1 2.0 1.0 2.8 1.3
স্যুইচ-রেঞ্জ 38.1 10.6 2.6 7.3 20.9 10.4
স্যুইচ-রেঞ্জ 2 31.9 8.3 2.0 4.5 9.5 6.9
সুইচ-অপ্রত্যক্ষ-অ্যারে 35.2 9.6 4.2 5.5 10.7 8.6
অ্যারে-লিনিয়ার-স্যুইচ 3.6 4.1 4.5 10.0 4.7 2.7
অ্যারে-বাইনারি-স্যুইচ 7.8 6.7 9.5 16.0 15.0 4.9

টেস্ট যেখানে উইন্ডোজ 7 folowing সংস্করণের সাথে 32bit সম্পাদনা: ক্রোম 21.0.1180.89m , ফায়ারফক্স 15.0 , অপেরা 12,02 , MSIE 9.0.8112 , সাফারি 5.1.7নোডটি একটি লিনাক্স bit৪ বিট বাক্সে চালিত হয়েছিল কারণ উইন্ডোজের নোড.জেএস-তে টাইমার রেজোলিউশনটি 1 এমএসের পরিবর্তে 10 মিমি ছিল।

যদি-অবিলম্বে

এটি ... ড্রামরল এমএসআইই ব্যতীত সমস্ত পরীক্ষিত পরিবেশে সবচেয়ে দ্রুত ! (চমক চমক). এটি এটি প্রয়োগ করার প্রস্তাবিত উপায়।

if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else

যদি-পরোক্ষ

এই একটি বৈকল্পিক switch-indirect-arrayকিন্তু ifদ্রুত তুলনায় অনেক বদলে -statements এবং সঞ্চালিত switch-indirect-arrayপ্রায় সব পরীক্ষিত পরিবেশে।

values=[
   1000,  2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else

সুইচ-অবিলম্বে

এটি সমস্ত পরীক্ষিত পরিবেশে বেশ দ্রুত এবং আসলে এমএসআইইতে সবচেয়ে দ্রুত। এটি কাজ করে যখন আপনি কোনও সূচক পাওয়ার জন্য কোনও গণনা করতে পারেন।

switch (Math.floor(val/1000)) {
  case 0: /* do something */ break;
  case 1: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

সুইচ পরিসরের

এটি অপেরা ব্যতীত সমস্ত পরীক্ষিত পরিবেশের দ্রুততম তুলনায় প্রায় 6 থেকে 40 গুণ ধীর, যেখানে প্রায় দেড় গুণ সময় লাগে takes এটি ধীরে ধীরে কারণ ইঞ্জিনকে প্রতিটি মামলার জন্য দুবারের মান তুলনা করতে হয়। আশ্চর্যজনকভাবে ক্রোমের দ্রুততম অপারেশনের তুলনায় ক্রোমটি এটি সম্পূর্ণ করতে প্রায় 40 গুণ বেশি সময় নেয়, যখন এমএসআইই কেবল 6 বার সময় নেয়। তবে আসল সময়ের পার্থক্যটি ছিল মাত্র ms 74 মিলিয়ন এমএসআইইর পক্ষে ১৩3737ms (!)।

switch (true) {
  case (0 <= val &&  val < 1000): /* do something */ break;
  case (1000 <= val &&  val < 2000): /* do something */ break;
  ...
  case (29000 <= val &&  val < 30000): /* do something */ break;
}

সুইচ-ব্যাপ্তি 2

এটির একটি রূপ switch-rangeতবে প্রতি কেস কেবলমাত্র একটি তুলনা এবং অতএব দ্রুত, তবে অপেরা বাদে খুব ধীর। কেস স্টেটমেন্টের ক্রমটি গুরুত্বপূর্ণ কারণ ইঞ্জিন প্রতিটি ক্ষেত্রে উত্স কোড অর্ডারে ECMAScript262 পরীক্ষা করবে : 5 12.11

switch (true) {
  case (val < 1000): /* do something */ break;
  case (val < 2000): /* do something */ break;
  ...
  case (val < 30000): /* do something */ break;
}

সুইচ-পরোক্ষ-বিন্যস্ত

এই রূপটিতে রেঞ্জগুলি একটি অ্যারেতে সংরক্ষণ করা হয়। এটি সমস্ত পরীক্ষিত পরিবেশে ধীর এবং Chrome এ খুব ধীর।

values=[1000,  2000 ... 29000, 30000];

switch(true) {
  case (val < values[0]): /* do something */ break;
  case (val < values[1]): /* do something */ break;
  ...
  case (val < values[29]): /* do something */ break;
}

অ্যারে-রৈখিক-অনুসন্ধান

এটি একটি অ্যারের মানগুলির রৈখিক অনুসন্ধান এবং স্থির মানগুলির সাথে স্যুইচ বিবৃতি সংমিশ্রণ। যখন কেউ এটি ব্যবহার করতে পারে তার কারণ হ'ল যখন রানটাইম পর্যন্ত মানগুলি জানা যায় না। এটি প্রতিটি পরীক্ষিত পরিবেশে ধীর এবং এমএসআইইতে প্রায় 10 গুণ সময় নেয়।

values=[1000,  2000 ... 29000, 30000];

for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
  if (val < values[sidx]) break;
}

switch (sidx) {
  case 0: /* do something */ break;
  case 1: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

অ্যারে-বাইনারি-সুইচ

এটি array-linear-switchবাইনারি অনুসন্ধানের সাথে পরিবর্তিত। দুর্ভাগ্যক্রমে এটি লিনিয়ার অনুসন্ধানের চেয়ে ধীর। আমি জানি না এটি আমার বাস্তবায়ন কিনা বা লিনিয়ার অনুসন্ধানটি আরও অনুকূলিত হয় কিনা। এটিও হতে পারে যে কী স্পেসটি ছোট।

values=[0, 1000,  2000 ... 29000, 30000];

while(range) {
  range = Math.floor( (smax - smin) / 2 );
  sidx = smin + range;
  if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}

switch (sidx) {
  case 0: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

উপসংহার

কর্মক্ষমতা যদি গুরুত্বপূর্ণ হয় তবে ifস্টেস্টমেন্ট বা switchতাত্ক্ষণিক মান সহ ব্যবহার করুন ।


128
এই খুব বিশদ এবং পরিপাটি কাঠামো সহ উত্তর দেখতে বিরল। বড় +1
রিক দোনোহো

10
এই সমস্যার পারফরম্যান্সের ব্যাখ্যার জন্য বড় +1!
জোল্টন শ্মিড্ট

16
এই কারণেই উত্তরগুলির জন্য সেরা স্থানগুলির মধ্যে স্ট্যাকওভারফ্লো অন্যতম। এটি একটি "কালজয়ী" উত্তর, দুর্দান্ত কাজ এবং জিসফিলের জন্য ধন্যবাদ!
জেসি

1
grt তথ্য ও ব্যাখ্যা
জয়কান্দরী

3
আমি সত্যিই চাই আমি +2 করতে পারি, এরকম বিস্তারিত উত্তর!
কাস্পার লি

96

একটি বিকল্প:

var scrollleft = 1000;
switch (true)
{
    case (scrollleft > 1000):
      alert('gt');
      break;
    case (scrollleft <= 1000):
      alert('lt');
      break; 
}

ডেমো: http://jsfiddle.net/UWYzr/


4
এটি একটি আরও মূল্যবান সমাধান। +1
ইকনডিভিডবি 0

1
এটি কি ঠিক একইরকম নয় if(...) else if(...)? এটি এড়াতে পারে ifতবে আমার কাছে বেশ সুন্দর প্রতিস্থাপনের মতো শোনাচ্ছে না।
pimvdb

7
কোডে মার্জিত থাকাকালীন এটি কার্য সম্পাদনকে ব্যথা দেয়। ifস্টেটমেন্ট ব্যবহারের তুলনায় এটি ক্রোমের প্রায় 30 গুণ বেশি ধীর । আমার উত্তর এখানে দেখুন
কিছু

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

1
আমি ঠিক এটিই খুঁজছিলাম। ধন্যবাদ!
অমি শ্রেইবার

23
switch (Math.floor(scrollLeft/1000)) {
  case 0: // (<1000)
   //do stuff
   break;
  case 1: // (>=1000 && <2000)
   //do stuff;
   break;
}

আপনার যদি নিয়মিত পদক্ষেপ থাকে কেবল তখনই কাজ করে ...

সম্পাদনা করুন: যেহেতু এই দ্রবণটি আপোশ পেতে থাকে, তাই আমার অবশ্যই পরামর্শ দেওয়া উচিত যে মফোলোর দ্রবণটি আরও ভাল উপায়


1
আমি Math.round(scrollLeft/1000)উপায় দ্বারা ব্যবহৃত ।
সুইটজ

@ সুইটজ - শুধু মনে রাখবেন যে 999 <1000 কেস 0 এর ক্ষেত্রে পড়ে তবে ম্যাথ.াউন্ড (999/1000) কেস 1-এ পড়ে যায়। এছাড়াও, উপরে একটি টাইপও রয়েছে, সেই ক্ষেত্রে 1 হল> = 1000, কেবল> 1000 নয় ।
ইগর 18

মফোলোর সমাধানে কেবল সমস্যাটি হ'ল এটি ক্রোমে IcanDivideBy0 এর চেয়ে 30 গুণ বেশি ধীর। আমার উত্তর নীচে।
কিছু 9

6

আপনি মানদণ্ড এবং মানদণ্ডের সাথে সম্পর্কিত ফাংশন সহ একটি কাস্টম অবজেক্ট তৈরি করতে পারেন

var rules = [{ lowerLimit: 0,    upperLimit: 1000, action: function1 }, 
             { lowerLimit: 1000, upperLimit: 2000, action: function2 }, 
             { lowerLimit: 2000, upperLimit: 3000, action: function3 }];

এই ক্ষেত্রে আপনি যা করতে চান তার জন্য ফাংশনগুলি সংজ্ঞায়িত করুন (ফাংশন 1, ফাংশন 2 ইত্যাদি সংজ্ঞায়িত করুন)

এবং নিয়মগুলি "মূল্যায়ন" করুন

function applyRules(scrollLeft)
{
   for(var i=0; i>rules.length; i++)
   {
       var oneRule = rules[i];
       if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit)
       {
          oneRule.action();
       }
   }
}

বিঃদ্রঃ

আমি বিবৃতি যদি 30 ব্যবহার করে ঘৃণা করি

স্টেটমেন্টগুলি পড়া এবং বজায় রাখা সহজ হয় তবে অনেক সময়। আমি কেবল তখন উপরেরটি সুপারিশ করব যখন আপনার অনেক শর্ত এবং ভবিষ্যতে প্রচুর বিকাশের সম্ভাবনা থাকে ।

আপডেট
হিসাবে @ ব্র্যাড মন্তব্যে উল্লেখ করেছেন, শর্তগুলি যদি পারস্পরিক একচেটিয়া হয় (তবে তাদের মধ্যে কেবলমাত্র একবারে সত্য হতে পারে), উপরের সীমাটি পরীক্ষা করা যথেষ্ট হবে:

if(scrollLeft < oneRule.upperLimit)

প্রদত্ত যে অবস্থার আরোহী অনুক্রমে সংজ্ঞায়িত করা হয় (প্রথম সর্বনিম্ন এক, 0 to 1000এবং তারপর 1000 to 2000উদাহরণস্বরূপ)


action=function1- এগুলি কলোন হওয়া উচিত নয়? ;-) - আপনি এটিকে কেবলমাত্র একটি উচ্চতর সীমা রাখতে রিফ্যাক্টর করতে পারেন, কারণ নির্মূল প্রক্রিয়াটির কারণে আপনি দুটি গ্রুপের মধ্যে পড়তে পারবেন না - যদি না তা আপনার উদ্দেশ্য ছিল (একাধিক ক্রিয়াকলাপ সম্ভব)।
ব্র্যাড ক্রিস্টি

@ ব্র্যাড ক্রিস্টি অফ কোর্স
নিবাস

@ ব্র্যাড, না এটি আমার উদ্দেশ্য ছিল না এবং আপনি ঠিক বলেছেন, উপরের সীমাটি যথেষ্ট হবে। এটি আপডেট হিসাবে যুক্ত করবে ...
নিবাস

আমি এটি একটি সংক্ষিপ্ত এবং পরিষ্কার +1
pimvdb

3

আপনি ঠিক কি করছেন //do stuff?

আপনি যেমন কিছু করতে সক্ষম হতে পারেন:

(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc. 

3

এটি কাজ করবে কিনা তা পরীক্ষা না করা এবং অনিশ্চিত, তবে এর if statementsজন্য ভেরিয়েবল সেট করার জন্য কেন আগে কিছু করা হবে না switch statement

var small, big;

if(scrollLeft < 1000){
    //add some token to the page
    //call it small
}


switch (//reference token/) {
  case (small):
   //do stuff
   break;
  case (big):
   //do stuff;
   break;
}

2

এটি অন্য বিকল্প:

     switch (true) {
         case (value > 100):
             //do stuff
             break;
         case (value <= 100)&&(value > 75):
             //do stuff
             break;
         case (value < 50):
            //do stuff
             break;
     }

1

গৃহীত উত্তর আপডেট করা (এখনও মন্তব্য করতে পারে না)। 1/12/16 ক্রোমে ডেমো জেসফিডাল ব্যবহার করে, স্যুইচ-তাত্ক্ষণিকতম দ্রুত সমাধান।

ফলাফল: সময় রেজোলিউশন: 1.33

   25ms "if-immediate" 150878146 
   29ms "if-indirect" 150878146
   24ms "switch-immediate" 150878146
   128ms "switch-range" 150878146
   45ms "switch-range2" 150878146
   47ms "switch-indirect-array" 150878146
   43ms "array-linear-switch" 150878146
   72ms "array-binary-switch" 150878146

সমাপ্ত

 1.04 (   25ms) if-immediate
 1.21 (   29ms) if-indirect
 1.00 (   24ms) switch-immediate
 5.33 (  128ms) switch-range
 1.88 (   45ms) switch-range2
 1.96 (   47ms) switch-indirect-array
 1.79 (   43ms) array-linear-switch
 3.00 (   72ms) array-binary-switch

এটি সত্যই নির্ভর করে - 15 মিমি "যদি-তাত্ক্ষণিক" 15ms "যদি-পরোক্ষ" 15 মিমি "স্যুইচ-তাত্ক্ষণিক" 37 মিমি "স্যুইচ-রেঞ্জ" 28 মিমি "স্যুইচ-রেঞ্জ 2" 35 মিমি "স্যুইচ-অপ্রত্যক্ষ-অ্যারে" 29 মিমি "অ্যারে-লিনিয়ার-সুইচ" 62ms "অ্যারে-বাইনারি-স্যুইচ" সমাপ্ত 1.00 (15 মিমি) যদি-তাত্ক্ষণিক 1.00 (15 মিমি) যদি-পরোক্ষ 1.00 (15 মিমি) স্যুইচ-তাত্ক্ষণিক 2.47 (37 মিমি) স্যুইচ-রেঞ্জ 1.87 (28 মিমি) স্যুইচ-রেঞ্জ 2 2.33 (35 মিমি) স্যুইচ- পরোক্ষ-অ্যারে 1.93 (29 মিমি) অ্যারে-রৈখিক-সুইচ 4.13 (62 মিমি) অ্যারে-বাইনারি-স্যুইচ ক্রোম সংস্করণ 48.0.2564.109 (64-বিট) ম্যাক ওএস x 10.11.3
রেনেসাঁসূত্র প্রোগ্রামার

ম্যাক ওএস এক্স এবং এটি সাফারি আইওএস 9.3 এ এটিএম সাফারি 9. এক্স, "যদি-তাত্ক্ষণিক" স্পষ্ট বিজয়ী
রেনেসাঁসূত্র প্রোগ্রাম

1
1 এমএস পার্থক্য যত্ন নেওয়ার পক্ষে খুব কম। এটি প্রতিটি পরীক্ষার রান থেকে আলাদা হয় vary কথাটি হ'ল: কোডিং শৈলীটি বোঝার জন্য ব্যবহার করুন এবং মাইক্রো-অপ্টিমাইজ করার চেষ্টা করবেন না।
কিছু

1

আমার ক্ষেত্রে (শতাংশে রঙ-কোডিং, পারফরম্যান্স-সমালোচনামূলক কিছুই নয়), আমি দ্রুত এটি লিখেছিলাম:

function findColor(progress) {
    const thresholds = [30, 60];
    const colors = ["#90B451", "#F9A92F", "#90B451"];

    return colors.find((col, index) => {
        return index >= thresholds.length || progress < thresholds[index];
    });
}

1

আমি বিবৃতি যদি 30 ব্যবহার করে ঘৃণা করি

ইদানীং আমার একই পরিস্থিতি ছিল, আমি এটি সমাধান করেছি:

আগে:

if(wind_speed >= 18) {
    scale = 5;
} else if(wind_speed >= 12) {
    scale = 4;
} else if(wind_speed >= 9) {
    scale = 3;
} else if(wind_speed >= 6) {
    scale = 2;
} else if(wind_speed >= 4) {
    scale = 1;
}

পরে:

var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]];
scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]});

এবং যদি আপনি "1, 2, 3, 4, 5" সেট করেন তবে এটি আরও সহজ হতে পারে:

var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.