ইএস in (ইসিএমএএসক্রিপ্ট)) এ পারস্পরিক পরিবর্তনশীলগুলি ছাড়াই x বার লুপ করার কোনও ব্যবস্থা আছে?


156

xজাভাস্ক্রিপ্টে লুপ বারের সাধারণ উপায় হ'ল:

for (var i = 0; i < x; i++)
  doStuff(i);

তবে আমি ++অপারেটরটি ব্যবহার করতে চাই না বা কোনও মিউটেটেবল ভেরিয়েবলগুলি রাখতে চাই না। ES6 এ লুপ xবারের অন্য উপায়ে উপায় আছে কি? আমি রুবির প্রক্রিয়া ভালবাসি:

x.times do |i|
  do_stuff(i)
end

জাভাস্ক্রিপ্ট / ইএস 6 এর মতো কিছু? আমি এক প্রকারের ঠকাই এবং নিজের জেনারেটর তৈরি করতে পারি:

function* times(x) {
  for (var i = 0; i < x; i++)
    yield i;
}

for (var i of times(5)) {
  console.log(i);
}

অবশ্যই আমি এখনও ব্যবহার করছি i++। কমপক্ষে এটি দৃষ্টির বাইরে নয় :), তবে আমি আশা করছি যে ES6 এর মধ্যে আরও ভাল ব্যবস্থা রয়েছে।


3
কেন পরিবর্তনীয় লুপ নিয়ন্ত্রণ পরিবর্তনশীল একটি সমস্যা? শুধু একটি নীতি?

1
@ ডলড্ট - আমি জাভাস্ক্রিপ্ট শেখানোর চেষ্টা করছি, তবে পরে পরিবর্তনশীল ভেরিয়েবলের ধারণাটি বিলম্ব করার সাথে পরীক্ষা করছি

5
আমরা এখানে প্রকৃতপক্ষে অফ-টপিক পাচ্ছি, তবে আপনি কি নিশ্চিত যে ES6 জেনারেটরগুলিতে (বা অন্য কোনও নতুন, উচ্চ স্তরের ধারণা) পরিবর্তন করা ভাল ধারণা যা তারা পরিবর্তনীয় ভেরিয়েবল সম্পর্কে শিখার আগে? :)
ডল্ট

5
@ ডলড্ট - সম্ভবত, আমি পরীক্ষা নিরীক্ষা করছি। জাভাস্ক্রিপ্টে কার্যকরী ভাষা গ্রহণ করা।
এ।

উত্তর:


156

ঠিক আছে!

নীচের কোডটি ES6 সিনট্যাক্স ব্যবহার করে লেখা হয়েছে তবে কেবল সহজেই ES5 বা তার চেয়েও কম লেখা যেতে পারে। ES6 কোনও "x বার লুপ করার পদ্ধতি" তৈরি করার প্রয়োজন হয় না


যদি কলব্যাকে আপনার পুনরুক্তি প্রয়োজন না হয় তবে এটি সর্বাধিক সাধারণ বাস্তবায়ন

const times = x => f => {
  if (x > 0) {
    f()
    times (x - 1) (f)
  }
}

// use it
times (3) (() => console.log('hi'))

// or define intermediate functions for reuse
let twice = times (2)

// twice the power !
twice (() => console.log('double vision'))

যদি আপনার পুনরুক্তি প্রয়োজন হয় , আপনি আপনার জন্য পুনরাবৃত্তি করতে একটি কাউন্টার প্যারামিটার সহ একটি নামকৃত অভ্যন্তরীণ ফাংশন ব্যবহার করতে পারেন

const times = n => f => {
  let iter = i => {
    if (i === n) return
    f (i)
    iter (i + 1)
  }
  return iter (0)
}

times (3) (i => console.log(i, 'hi'))


আপনি যদি আরও কিছু শিখতে পছন্দ না করেন তবে এখানে পড়া বন্ধ করুন ...

তবে সেগুলি সম্পর্কে কিছু মনে করা উচিত ...

  • একক শাখার ifবিবৃতি কুৎসিত - অন্য শাখায় কী ঘটে?
  • ফাংশন বডিগুলিতে একাধিক বিবৃতি / অভিব্যক্তি - প্রক্রিয়া উদ্বেগগুলি মিশ্রিত হচ্ছে?
  • স্পষ্টভাবে প্রত্যাবর্তন undefined- অপরিষ্কার ইঙ্গিত, পার্শ্ব-প্রভাব কার্যকারিতা

"এর চেয়ে ভাল উপায় আর নেই?"

এখানে. আসুন প্রথমে আমাদের প্রাথমিক প্রয়োগটি আবার ঘুরে দেখি

// times :: Int -> (void -> void) -> void
const times = x => f => {
  if (x > 0) {
    f()               // has to be side-effecting function
    times (x - 1) (f)
  }
}

অবশ্যই, এটি সহজ, তবে লক্ষ্য করুন যে আমরা কীভাবে কল করি f()এবং এটি দিয়ে কিছু না করি। এটি সত্যিই এমন এক ধরণের ক্রিয়াকে সীমাবদ্ধ করে যা আমরা একাধিকবার পুনরাবৃত্তি করতে পারি। আমাদের কাছে পুনরুক্তি উপলব্ধ থাকলেও, f(i)এটি আরও বহুমুখী নয়।

যদি আমরা আরও ভাল ধরণের ফাংশন পুনরাবৃত্তি পদ্ধতি দিয়ে শুরু করি তবে কী হবে? হয়ত এমন কিছু যা ইনপুট এবং আউটপুটটির আরও ভাল ব্যবহার করে।

জেনেরিক ফাংশন পুনরাবৃত্তি

// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
  if (n > 0)
    return repeat (n - 1) (f) (f (x))
  else
    return x
}

// power :: Int -> Int -> Int
const power = base => exp => {
  // repeat <exp> times, <base> * <x>, starting with 1
  return repeat (exp) (x => base * x) (1)
}

console.log(power (2) (8))
// => 256

উপরে, আমরা একটি জেনেরিক সংজ্ঞায়িত করেছি repeat ফাংশন যা অতিরিক্ত ইনপুট নেয় যা একক ফাংশনের পুনরাবৃত্তি প্রয়োগ শুরু করতে ব্যবহৃত হয়।

// repeat 3 times, the function f, starting with x ...
var result = repeat (3) (f) (x)

// is the same as ...
var result = f(f(f(x)))

বাস্তবায়নকারী times সঙ্গেrepeat

আচ্ছা এটি এখন সহজ; প্রায় সব কাজ ইতিমধ্যে সম্পন্ন হয়েছে।

// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
  if (n > 0)
    return repeat (n - 1) (f) (f (x))
  else
    return x
}

// times :: Int -> (Int -> Int) -> Int 
const times = n=> f=>
  repeat (n) (i => (f(i), i + 1)) (0)

// use it
times (3) (i => console.log(i, 'hi'))

যেহেতু আমাদের ফাংশনটি iএকটি ইনপুট হিসাবে নেয় এবং ফিরে আসেi + 1 , এটি কার্যকরভাবে আমাদের পুনরাবৃত্তকারী হিসাবে কাজ করে যা আমরা fপ্রতিটি সময়কে পাস করি ।

আমরা আমাদের বুলেট তালিকাগুলির তালিকাও ঠিক করেছি

  • আর কুরুচিপূর্ণ একক শাখা নেই if বিবৃতি নেই
  • একক-প্রকাশের দেহগুলি সুন্দরভাবে বিচ্ছিন্ন উদ্বেগগুলি নির্দেশ করে
  • আর অকেজো, স্পষ্টভাবে ফিরে আসেনি undefined

জাভাস্ক্রিপ্ট কমা অপারেটর,

শেষ উদাহরণটি কীভাবে কাজ করছে তা দেখতে আপনার যদি সমস্যা হয় তবে এটি জাভাস্ক্রিপ্টের প্রাচীনতম যুদ্ধ অক্ষগুলির একটি সম্পর্কে আপনার সচেতনতার উপর নির্ভর করে; কমা অপারেটর - সংক্ষিপ্ত, এটা এক্সপ্রেশন বাঁ দিক থেকে ডানদিকে মূল্যায়ণ এবং ফেরৎ গত মূল্যায়ন মত প্রকাশের মান

(expr1 :: a, expr2 :: b, expr3 :: c) :: c

আমাদের উপরের উদাহরণে, আমি ব্যবহার করছি

(i => (f(i), i + 1))

এটি কেবল লেখার একটি সংক্ষিপ্ত উপায়

(i => { f(i); return i + 1 })

টেল কল অপটিমাইজেশন

পুনরাবৃত্তিমূলক বাস্তবায়ন যেমন সেক্সি, এই মুহুর্তে জাভাস্ক্রিপ্ট ভিএম না থাকায় তাদের সুপারিশ করা আমার পক্ষে দায়িত্বজ্ঞানজনক হবে না আমি যথাযথ লেজ কল নির্মূলের পক্ষে সমর্থন করতে পারে না - বাবেল এটি প্রতিস্থাপন করতে ব্যবহৃত হয়েছিল, তবে এটি "ভাঙ্গা; পুনরায় প্রতিস্থাপন করবে" "এক বছরেরও বেশি সময় ধরে স্ট্যাটাস।

repeat (1e6) (someFunc) (x)
// => RangeError: Maximum call stack size exceeded

এর মতো, আমাদের বাস্তবায়নের পুনর্বিবেচনা করা উচিত repeat এটিকে স্ট্যাক-নিরাপদ করতে ।

নিচের কোড আছে চপল বিকল্পগুলি ব্যবহার nএবং xকিন্তু মনে রাখবেন যে সমস্ত পরিব্যক্তি থেকে অনূদিত হয় repeatকোন রাষ্ট্র পরিবর্তনগুলি (পরিব্যক্তি) ফাংশনের বাইরে থেকে দৃশ্যমান - ফাংশন

// repeat :: Int -> (a -> a) -> (a -> a)
const repeat = n => f => x =>
  {
    let m = 0, acc = x
    while (m < n)
      (m = m + 1, acc = f (acc))
    return acc
  }

// inc :: Int -> Int
const inc = x =>
  x + 1

console.log (repeat (1e8) (inc) (0))
// 100000000

এটি আপনার প্রচুর বক্তব্য রাখবে "তবে এটি কার্যকরী নয়!" - আমি জানি, আরাম করুন। আমরা খাঁটি অভিব্যক্তি ব্যবহার করে ধ্রুবক-স্থান লুপিংয়ের জন্য ক্লোজার-স্টাইল loop/ recurইন্টারফেস প্রয়োগ করতে পারি ; এগুলোর একটাও নাwhile জিনিস কিছুই।

এখানে আমরা whileআমাদের loopফাংশনটি বিমূর্ত করি - recurলুপটি চালিয়ে যাওয়ার জন্য এটি একটি বিশেষ ধরণের সন্ধান করে। যখন কোনও অ- recurটাইপের সম্মুখীন হয়, লুপটি সমাপ্ত হয় এবং গণনার ফলাফল ফিরে আসে

const recur = (...args) =>
  ({ type: recur, args })
  
const loop = f =>
  {
    let acc = f ()
    while (acc.type === recur)
      acc = f (...acc.args)
    return acc
  }

const repeat = $n => f => x =>
  loop ((n = $n, acc = x) =>
    n === 0
      ? acc
      : recur (n - 1, f (acc)))
      
const inc = x =>
  x + 1

const fibonacci = $n =>
  loop ((n = $n, a = 0, b = 1) =>
    n === 0
      ? a
      : recur (n - 1, b, a + b))
      
console.log (repeat (1e7) (inc) (0)) // 10000000
console.log (fibonacci (100))        // 354224848179262000000


24
অতিরিক্ত জটিল বলে মনে হচ্ছে (আমি বিশেষত বিভ্রান্ত হয়েছি g => g(g)(x))। আমার সলিউশনের মতো প্রথম-অর্ডারের চেয়ে উচ্চতর আদেশ ক্রিয়াকলাপ থেকে কি কোনও সুবিধা আছে?
পাভলো

1
@ নোমিক: একটি লিঙ্ক পোস্ট করার জন্য সময় দেওয়ার জন্য ধন্যবাদ। অনেক প্রশংসিত.
Pineda

1
@ আলফোনসো পেরেজ আমি এই মন্তব্যটির প্রশংসা করি। আমি সেখানে কোথাও কিছুটা ইঙ্গিত দিয়ে কাজ করতে পারি কিনা তা আমি দেখতে পাচ্ছি ^ _ ^
আপনাকে ধন্যবাদ

1
@naomik ফেয়ারওয়েল TCO ! আমি বিধ্বস্ত।

10
দেখে মনে হচ্ছে এই উত্তরটি গৃহীত হয়েছে এবং ভালভাবে রেটে গেছে কারণ এটি অবশ্যই প্রচুর পরিশ্রম করেছে, তবে আমি মনে করি এটি ভাল উত্তর নয়। প্রশ্নের সঠিক উত্তর হ'ল "না"। আপনি যেমনটি করেছেন তেমন কাজের তালিকা তৈরি করা সহায়ক, তবে ঠিক এর পরে আপনি বলে দিয়েছেন যে আরও ভাল উপায় আছে। আপনি কেন এই উত্তরটি রেখেছেন না এবং শীর্ষে থাকা খারাপটি সরাচ্ছেন? কেন আপনি কমা অপারেটরদের ব্যাখ্যা দিচ্ছেন? আপনি ক্লোজুর আনছেন কেন? কেন, সাধারণভাবে, 2 টি চরিত্রের উত্তর সহ একটি প্রশ্নের জন্য এতগুলি স্পর্শকাতর? সাধারণ প্রশ্নগুলি কিছু ঝরঝরে প্রোগ্রামিংয়ের তথ্যের উপর উপস্থাপনা করার জন্য কেবল প্ল্যাটফর্ম নয়।
টিমোফিয়ে 'সাশা' কন্ড্রাশভ

264

ES2015 স্প্রেড অপারেটরটি ব্যবহার করে :

[...Array(n)].map()

const res = [...Array(10)].map((_, i) => {
  return i * 10;
});

// as a one liner
const res = [...Array(10)].map((_, i) => i * 10);

অথবা যদি আপনার ফলাফলের প্রয়োজন না হয়:

[...Array(10)].forEach((_, i) => {
  console.log(i);
});

// as a one liner
[...Array(10)].forEach((_, i) => console.log(i));

অথবা ES2015 অ্যারে.ফর্ম অপারেটরটি ব্যবহার করে :

Array.from(...)

const res = Array.from(Array(10)).map((_, i) => {
  return i * 10;
});

// as a one liner
const res = Array.from(Array(10)).map((_, i) => i * 10);

নোট করুন যে আপনার যদি কেবল স্ট্রিংয়ের প্রয়োজন হয় তবে আপনি স্ট্রিং.প্রোটোটাইপ.রেপ্যাট ব্যবহার করতে পারেন ।

console.log("0".repeat(10))
// 0000000000

26
আরও ভাল:Array.from(Array(10), (_, i) => i*10)
বার্গি

6
এটি সেরা উত্তর হওয়া উচিত। সুতরাং ES6! অনেক দুর্দান্ত!
জার্জি ফেহারিভরি

3
যদি আপনার পুনরুক্তি প্রয়োজন না (i), আপনি এটি তৈরি করতে কী এবং মান উভয়ই বাদ দিতে পারেন:[...Array(10)].forEach(() => console.log('looping 10 times');
স্টার্লিং বোর্ন

9
সুতরাং আপনি কেবলমাত্র এটিকে ফেলে দেওয়ার জন্য এন উপাদানগুলির পুরো অ্যারে বরাদ্দ করেন ?
কুগেল

2
কেউ কি কুগেলের আগের মন্তব্যে সম্বোধন করেছেন? আমি একই জিনিসটি ভাবছিলাম
আরমান

37
for (let i of Array(100).keys()) {
    console.log(i)
}

এটি কাজ করে, তাই দুর্দান্ত! তবে এই বিবেচনায় কিছুটা কুৎসিত যে অতিরিক্ত কাজ করা দরকার এবং Arrayকীগুলি এর জন্য ব্যবহৃত হয় তা নয় ।
এ।

@at। প্রকৃতপক্ষে. তবে আমি নিশ্চিত নই যে [0..x]আমার উত্তরের চেয়ে জেএসে আরও একটি সংক্ষিপ্ততর শব্দটির প্রতিশব্দ রয়েছে ।
zerkms

আপনি সঠিক হতে পারেন যে এর চেয়ে সংক্ষিপ্ত কিছুই নেই।
এ।

ঠিক আছে, আমি বুঝতে পারি যে এটি কেন কাজ করে এর মধ্যে পার্থক্য Array.prototype.keys এবং এরObject.prototype.keys তবে এটি নিশ্চিত প্রথম নজরে বিভ্রান্তিকর।
মার্ক রিড

1
ES2015- এ টিসিওর সাথে @ চ্যাম্বারলাইন (যদিও কোথাও বাস্তবায়ন হয়নি?) এটি উদ্বেগের পরিমাণ কম হতে পারে, তবে সত্যই :-)
পরিমাণটি জেরকামস

29

আমি মনে করি সবচেয়ে ভাল সমাধানটি ব্যবহার করা let:

for (let i=0; i<100; i++) 

এটি iপ্রতিটি দেহের মূল্যায়নের জন্য একটি নতুন (পরিবর্তনীয়) পরিবর্তনশীল তৈরি করবে এবং আশ্বাস দেয় যে iকেবলমাত্র সেই লুপ বাক্য বাক্সে বর্ধিত অভিব্যক্তিতে পরিবর্তিত হয়েছে, অন্য কোথাও নয়।

আমি এক ধরণের প্রতারণা করতে এবং নিজের জেনারেটর তৈরি করতে পারি। কমপক্ষে i++দৃষ্টিগোচর নয় :)

এটি যথেষ্ট ইমো হওয়া উচিত। এমনকি খাঁটি ভাষায় সমস্ত ক্রিয়াকলাপ (বা কমপক্ষে, তাদের দোভাষী) আদিম থেকে নির্মিত যা রূপান্তর ব্যবহার করে। যতক্ষণ না এটি যথাযথভাবে স্কোপ করা হয় ততক্ষণ আমি দেখতে পাচ্ছি না যে এতে কী ভুল।

আপনার ভাল করা উচিত

function* times(n) {
  for (let i = 0; i < x; i++)
    yield i;
}
for (const i of times(5))
  console.log(i);

তবে আমি ++অপারেটরটি ব্যবহার করতে চাই না বা কোনও মিউটেটেবল ভেরিয়েবলগুলি রাখতে চাই না।

তারপরে আপনার একমাত্র পছন্দটি পুনরাবৃত্তি ব্যবহার করা use কোনও জেনারেটর ছাড়াই আপনি সেই জেনারেটরের ক্রিয়াকলাপটিকে সংজ্ঞায়িত করতে পারেন i:

function* range(i, n) {
  if (i >= n) return;
  yield i;
  return yield* range(i+1, n);
}
times = (n) => range(0, n);

তবে এটি আমার কাছে ওভারকিল বলে মনে হচ্ছে এবং এতে পারফরম্যান্সের সমস্যা হতে পারে (যেহেতু টেল কল নির্মূলের জন্য উপলব্ধ নয় return yield*)।


1
আমি এই বিকল্পটি পছন্দ করি - দুর্দান্ত এবং সহজ!
ড্যানভি

2
এটি সহজ এবং মূল বিষয় এবং উপরের অনেক উত্তরের মতো একটি অ্যারে বরাদ্দ করে না
কুগেল

@ কুগেল দ্বিতীয়টি স্ট্যাকের জন্য বরাদ্দ হতে পারে, যদিও
বার্গি

টেল-কল অপ্টিমাইজেশানটি এখানে কাজ করবে কিনা তা নিশ্চিত হওয়ার বিষয়টি নিশ্চিত নয় @ বার্গি
কুগেল

13
const times = 4;
new Array(times).fill().map(() => console.log('test'));

এই স্নিপেট console.log test4 বার হবে ।


পূরণের জন্য সমর্থন কি?
আমির আফ্রিদি

2
@ আমিরআফ্রিদি আপনি ব্রাউজারের সামঞ্জস্যতা বিভাগটি পরীক্ষা করতে পারেন, একটি পলিফিলও সরবরাহ করা আছে: ডেভেলপার.মোজিলা.আর.ইন.ইউএস
হোসাম মুরাদ


11

উত্তর: 09 ডিসেম্বর 2015

ব্যক্তিগতভাবে, আমি গ্রহণযোগ্য উত্তর সংক্ষিপ্ত (ভাল) এবং সংশ্লেষ (খারাপ) উভয়ই পেয়েছি। এই বিবৃতি প্রশংসনীয় হতে পারে বিষয়গত হতে পারে, সুতরাং দয়া করে এই উত্তরটি পড়ুন এবং দেখুন আপনি একমত বা অসম্মতি প্রকাশ করেছেন কিনা

প্রশ্নে দেওয়া উদাহরণটি ছিল রুবির মতো:

x.times do |i|
  do_stuff(i)
end

নীচে JS এ এটি প্রকাশ করার অনুমতি দিবে:

times(x)(doStuff(i));

কোডটি এখানে:

let times = (n) => {
  return (f) => {
    Array(n).fill().map((_, i) => f(i));
  };
};

এটাই!

সাধারণ উদাহরণ ব্যবহার:

let cheer = () => console.log('Hip hip hooray!');

times(3)(cheer);

//Hip hip hooray!
//Hip hip hooray!
//Hip hip hooray!

বিকল্পভাবে, গৃহীত উত্তরের উদাহরণ অনুসরণ করে:

let doStuff = (i) => console.log(i, ' hi'),
  once = times(1),
  twice = times(2),
  thrice = times(3);

once(doStuff);
//0 ' hi'

twice(doStuff);
//0 ' hi'
//1 ' hi'

thrice(doStuff);
//0 ' hi'
//1 ' hi'
//2 ' hi'

পার্শ্ব নোট - একটি পরিসীমা ফাংশন সংজ্ঞায়িত

একটি অনুরূপ / সম্পর্কিত প্রশ্ন, যা মূলত খুব অনুরূপ কোড কনস্ট্রাক্টস ব্যবহার করে, জাভা স্ক্রিপ্টে কোনও আরামদায়ক রেঞ্জ ফাংশন হতে পারে, আন্ডারস্কোরের রেঞ্জ ফাংশনের অনুরূপ কিছু।

X থেকে শুরু করে এন সংখ্যা সহ একটি অ্যারে তৈরি করুন

আন্ডারস্কোর

_.range(x, x + n)

ES2015

বিকল্প কয়েক:

Array(n).fill().map((_, i) => x + i)

Array.from(Array(n), (_, i) => x + i)

ডেমো এন = 10, এক্স = 1 ব্যবহার করে:

> Array(10).fill().map((_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

> Array.from(Array(10), (_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

দ্রুত পরীক্ষায় আমি দৌড়ে গিয়েছিলাম, উপরের প্রত্যেকে আমাদের সমাধান এবং ডুস্টফ ফাংশনটি ব্যবহার করে প্রতিটি মিলিয়ন বার চালিয়েছি, পূর্ববর্তী পদ্ধতির (অ্যারে (এন) .ফিল ()) কিছুটা দ্রুত প্রমাণিত হয়েছে।


8
Array(100).fill().map((_,i)=> console.log(i) );

এই সংস্করণ অপরিবর্তনীয়তার জন্য ওপির প্রয়োজনীয়তা পূরণ করে। reduceপরিবর্তে ব্যবহার বিবেচনা করুনmap আপনার ব্যবহারের ক্ষেত্রে নির্ভর করুন।

আপনি যদি নিজের প্রোটোটাইপে সামান্য পরিবর্তন আনতে চান না তবে এটিও একটি বিকল্প।

Number.prototype.times = function(f) {
   return Array(this.valueOf()).fill().map((_,i)=>f(i));
};

এখন আমরা এটি করতে পারি

((3).times(i=>console.log(i)));

পরামর্শের জন্য আর্কসেল্ডনকে +1 করুন .fill


ভোট দেওয়া হয়েছে, যেমন পূরণের পদ্ধতি IE বা অপেরা বা ফ্যান্টমজেএস
তে

8

এখানে আরও একটি ভাল বিকল্প রয়েছে:

Array.from({ length: 3}).map(...);

পছন্দ হিসাবে, @ ডেভ মোর্স মন্তব্যগুলিতে উল্লেখ করেছেন, আপনি এছাড়াও এ থেকে মুক্তি পেতে পারেন mapArray.from ফাংশনটির দ্বিতীয় প্যারামিটারটি এভাবে ব্যবহার করেও কলটি থেকে :

Array.from({ length: 3 }, () => (...))


2
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত! একটি ছোট পরামর্শ - আপনি ইতিমধ্যে Array.from({ length: label.length }, (_, i) => (...)) অ্যারে দিয়ে ফ্রি করার জন্য মানচিত্রের মতো কার্যকারিতা পেয়ে গেছেন। ক্রম: এটি মানচিত্রে কোনও কল বন্ধ করার জন্য একটি খালি অস্থায়ী অ্যারে তৈরি করে সংরক্ষণ করে।
ডেভ মোর্স

7

আমি শেখাত এমন কিছু নয় (বা আমার কোডটিতে কখনও ব্যবহার করুন), তবে এখানে কোনও ভেরিয়েবলকে পরিবর্তন না করেই একটি কোডগল্ফ-উপযুক্ত সমাধান রয়েছে, ES6 এর দরকার নেই:

Array.apply(null, {length: 10}).forEach(function(_, i){
    doStuff(i);
})

সত্যিকারের একটি দরকারী উত্তরের চেয়ে একটি আকর্ষণীয় প্রুফ-অফ-কনসেপ্ট জিনিস।


চুদি Array.apply(null, {length: 10})না Array(10)?
পাভলো

1
@ পাভলো, আসলে, না অ্যারে (10) 10 দৈর্ঘ্যের একটি অ্যারে তৈরি করবে, তবে এতে কোনও কী সংযুক্ত না করে, যা এই ক্ষেত্রে forEach নির্মাণকে ব্যবহারযোগ্য না করে তোলে। তবে প্রকৃতপক্ষে এটি সরল করা যেতে পারে যদি আপনি প্রত্যেকের জন্য ব্যবহার না করেন, জারকামসের উত্তর দেখুন (এটি যদিও ES6 ব্যবহার করে!)।
ডল্ট করেছেন

সৃজনশীল @ ডলড্ট, তবে আমি শিক্ষণযোগ্য এবং সাধারণ কিছু সন্ধান করছি।
এ।

5

আমি পার্টিতে দেরি করছি, তবে যেহেতু এই প্রশ্নটি প্রায়শই অনুসন্ধানের ফলাফলগুলিতে উত্থিত হয়, আমি কেবল একটি সমাধান যুক্ত করতে চাই যা আমি দীর্ঘায়িত না হয়ে পঠনযোগ্যতার দিক থেকে সেরা হিসাবে বিবেচনা করি (যা কোনও কোডবেস আইএমওর জন্য আদর্শ) । এটি পরিবর্তিত হয়, তবে আমি কেআইএসএস নীতিগুলির জন্য সেই ট্রেড অফ করব।

let times = 5
while( times-- )
    console.log(times)
// logs 4, 3, 2, 1, 0

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

timesলুপের অভ্যন্তরে ভেরিয়েবলটি ব্যবহার করতে চাইলে এটি কেবল সামান্য সামঞ্জস্যপূর্ণ itive সম্ভবত countdownএকটি ভাল নামকরণ হবে। অন্যথায়, পৃষ্ঠায় সবচেয়ে পরিষ্কার এবং পরিষ্কার উত্তর।
টনি ব্রাসুনাস

3

আফাইক, রুবির timesপদ্ধতির মতো ইএস 6 তে কোনও ব্যবস্থা নেই । তবে আপনি পুনরাবৃত্তি ব্যবহার করে পরিবর্তনকে এড়াতে পারবেন:

let times = (i, cb, l = i) => {
  if (i === 0) return;

  cb(l - i);
  times(i - 1, cb, l);
}

times(5, i => doStuff(i));

ডেমো: http://jsbin.com/koyecovano/1/edit?js,console


আমি এই পদ্ধতির পছন্দ করি, আমি পুনরাবৃত্তি পছন্দ করি। তবে আমি নতুন জাভাস্ক্রিপ্ট ব্যবহারকারী লুপগুলি দেখানোর জন্য আরও সহজ কিছু পছন্দ করব।
এ।

3

আপনি যদি কোনও লাইব্রেরি ব্যবহার করতে ইচ্ছুক হন তবে লড্যাশ_.times বা আন্ডারস্কোরটিও রয়েছে_.times :

_.times(x, i => {
   return doStuff(i)
})

নোট করুন এটি ফলাফলগুলির একটি অ্যারের রিটার্ন দেয়, সুতরাং এটি সত্যই আরও এই রুবির মতো:

x.times.map { |i|
  doStuff(i)
}

2

কার্যকরী দৃষ্টান্তে repeatসাধারণত একটি অসীম পুনরাবৃত্তি ফাংশন হয়। এটি ব্যবহারের জন্য আমাদের অলস মূল্যায়ন বা ধারাবাহিকতা পাস করার শৈলী প্রয়োজন।

অলস ফাংশন পুনরাবৃত্তি মূল্যায়ন

const repeat = f => x => [x, () => repeat(f) (f(x))];
const take = n => ([x, f]) => n === 0 ? x : take(n - 1) (f());

console.log(
  take(8) (repeat(x => x * 2) (1)) // 256
);

আমি জাভাস্ক্রিপ্টে অলস মূল্যায়ন অর্জন করতে একটি থঙ্ক (তর্ক ছাড়াই একটি ক্রিয়া) ব্যবহার করি।

ধারাবাহিকতা পাস করার শৈলীর সাথে ফাংশন পুনরাবৃত্তি

const repeat = f => x => [x, k => k(repeat(f) (f(x)))];
const take = n => ([x, k]) => n === 0 ? x : k(take(n - 1));

console.log(
  take(8) (repeat(x => x * 2) (1)) // 256
);

সিপিএস প্রথমে কিছুটা ভীতিজনক। যাইহোক, এটি সর্বদা একই প্যাটার্ন অনুসরণ করে: শেষ যুক্তি হল ধারাবাহিকতা (একটি ফাংশন), যা তার নিজের শরীরকে ডাকে:k => k(...) । দয়া করে মনে রাখবেন সিপিএস আউট ভিতরে আবেদন ফিরিয়ে নেবে, অর্থাত take(8) (repeat...)হয়ে k(take(8)) (...)যেখানে kআংশিকভাবে প্রয়োগ করা হয়repeat

উপসংহার

পুনরাবৃত্তি ( repeat) সমাপ্তির শর্ত ( take) কে পৃথক করে আমরা নমনীয়তা লাভ করি - উদ্বেগের বিভক্ততা এর তিক্ত সমাপ্তি পর্যন্ত: ডি


1

এই সমাধানের সুবিধা

  • পড়ার / ব্যবহারে সহজতম (imo)
  • রিটার্ন মানটি যোগফল হিসাবে ব্যবহার করা যেতে পারে, বা কেবল উপেক্ষা করা হবে
  • প্লেইন es6 সংস্করণ, এছাড়াও প্রতি সংযোগ আছে টাইপ করা বিষয় সংস্করণ কোডের

অসুবিধাগুলি - পরিবর্তন কেবল অভ্যন্তরীণ হওয়ার কারণে আমি পাত্তা দিই না, সম্ভবত কিছু অন্য কেউ তা করবে না।

উদাহরণ এবং কোড

times(5, 3)                       // 15    (3+3+3+3+3)

times(5, (i) => Math.pow(2,i) )   // 31    (1+2+4+8+16)

times(5, '<br/>')                 // <br/><br/><br/><br/><br/>

times(3, (i, count) => {          // name[0], name[1], name[2]
    let n = 'name[' + i + ']'
    if (i < count-1)
        n += ', '
    return n
})

function times(count, callbackOrScalar) {
    let type = typeof callbackOrScalar
    let sum
    if (type === 'number') sum = 0
    else if (type === 'string') sum = ''

    for (let j = 0; j < count; j++) {
        if (type === 'function') {
            const callback = callbackOrScalar
            const result = callback(j, count)
            if (typeof result === 'number' || typeof result === 'string')
                sum = sum === undefined ? result : sum + result
        }
        else if (type === 'number' || type === 'string') {
            const scalar = callbackOrScalar
            sum = sum === undefined ? scalar : sum + scalar
        }
    }
    return sum
}

TypeScipt সংস্করণ https://codepen.io/ whitneyland/pen/aVjaaE?editors=0011


0

কার্যকরী দিক সম্বোধন:

function times(n, f) {
    var _f = function (f) {
        var i;
        for (i = 0; i < n; i++) {
            f(i);
        }
    };
    return typeof f === 'function' && _f(f) || _f;
}
times(6)(function (v) {
    console.log('in parts: ' + v);
});
times(6, function (v) {
    console.log('complete: ' + v);
});

5
"কার্যকরী দিকটি সম্বোধন করা" এবং তারপরে একটি পরিবর্তনীয় দিয়ে অপরিহার্য লুপ ব্যবহার করা i। এমনকি timesপ্লেইন পুরানো ওপরে ব্যবহার করার কারণ কী for?
zerkms

পুনরায় ব্যবহার করুন var twice = times(2);
নিনা স্কলজ

তাহলে কেন শুধু forদুবার ব্যবহার করবেন না ?
zerkms

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

1
"ভ্যারিয়েবিল ব্যবহার না করার জন্য এটি ছিল" --- এবং আপনি এখনও এটি ব্যবহার করেন - i++। কোনও কার্যক্রমে অগ্রহণযোগ্য কিছু মোড়ানো কীভাবে এটি আরও ভাল করে তোলে তা স্পষ্ট নয়।
zerkms

0

জেনারেটর? Recursion? 'মুত্তাটিনে' এত হ্যাটিন কেন? ;-)

যদি আমরা এটি "আড়াল" না করি ততক্ষণ এটি যদি গ্রহণযোগ্য হয় তবে কেবল একটি অযৌক্তিক অপারেটরের ব্যবহারটি গ্রহণ করুন এবং আমরা জিনিসগুলি সহজ রাখতে পারি :

Number.prototype.times = function(f) { let n=0 ; while(this.valueOf() > n) f(n++) }

রুবির মতো:

> (3).times(console.log)
0
1
2

2
থাম্বস আপ: "কেন এত বেশি হ্যাটিন 'মুটাটিনে?"
সারেফ

1
সরলতার জন্য থাম্বস আপ, ম্যানিপ্যাচটির সাথে রুবি স্টাইলে কিছুটা বেশি যেতে হবে। এই খারাপ খারাপ বানরদের শুধু বলুন না।
মিঃ মিঃ

1
@ মিআরএম হ'ল এটি কি "বানরের প্যাচিং", এটি কি কেবল এক্সটেনশনের ঘটনা নয়? আলিঙ্গন করুন এবং প্রসারিত করুন :)
joiny

সংখ্যায় ফাংশন যুক্ত করা (বা স্ট্রিং বা অ্যারে বা অন্য কোনও শ্রেণি যা আপনি লেখেন নি) সংজ্ঞা অনুসারে, পলিফিল বা বানরের প্যাচগুলি - এমনকি পলিফিলগুলিও সুপারিশ করা হয় না। "বানর প্যাচ", "পলিফিল" এবং একটি প্রস্তাবিত বিকল্প "পনিফিল" এর সংজ্ঞাগুলি পড়ুন। তাহলে এটাই আপনি চান.
মিঃ মিঃ 31'17

আপনি যে সংখ্যাটি করবেন তা বাড়ানোর জন্য: ক্লাস সুপারমম্বারটি সংখ্যাটি {গুণ (fn) s এর জন্য প্রসারিত করে (আসুন i = 0; i <this; i ++) {fn (i); }}}
আলেকজান্ডার

0

আমি @ টাইম এর উত্তরটি একটি সহায়ক ফাংশন দিয়ে মুড়িয়েছি।

টাইপস্ক্রিপ্টে:

export const mapN = <T = any[]>(count: number, fn: (...args: any[]) => T): T[] => [...Array(count)].map((_, i) => fn())

এখন আপনি চালাতে পারেন:

const arr: string[] = mapN(3, () => 'something')
// returns ['something', 'something', 'something']
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.