আমি কীভাবে একটি কাস্টম পদক্ষেপ নিয়ে একটি পরিসীমা জুড়ে যেতে পারি?


100

আমি কীভাবে রাস্টের 1 টি ব্যতীত অন্য একটি পদক্ষেপের সাথে পরিসীমা নিয়ে পুনরাবৃত্তি করতে পারি? আমি সি ++ ব্যাকগ্রাউন্ড থেকে আসছি তাই আমি এর মতো কিছু করতে চাই

for(auto i = 0; i <= n; i+=2) {
    //...
}

মরিচায় আমার rangeফাংশনটি ব্যবহার করা দরকার এবং কাস্টম পদক্ষেপ নেওয়ার জন্য তৃতীয় যুক্তি রয়েছে বলে মনে হয় না। আমি কীভাবে এটি সম্পাদন করতে পারি?

উত্তর:


136

range_step_inclusiveএবং range_stepদীর্ঘ চলে গেছে।

মরিচা 1.28 হিসাবে, Iterator::step_byস্থিতিশীল:

fn main() {
    for x in (1..10).step_by(2) {
        println!("{}", x);
    }
}


নোট করুন যে এই পদ্ধতিটি 32 বিট আকারের ধরণের মেশিনগুলিতে 64 বিট পদক্ষেপ সমর্থন করবে না।
ব্যবহারকারী 202729

12

আমার কাছে মনে হয় যে .step_byপদ্ধতিটি স্থিতিশীল না হওয়া পর্যন্ত আপনি সহজেই যা করতে চান তা পূরণ করতে পারে Iterator(যা Rangeসত্যিই যাই হোক না কেন):

struct SimpleStepRange(isize, isize, isize);  // start, end, and step

impl Iterator for SimpleStepRange {
    type Item = isize;

    #[inline]
    fn next(&mut self) -> Option<isize> {
        if self.0 < self.1 {
            let v = self.0;
            self.0 = v + self.2;
            Some(v)
        } else {
            None
        }
    }
}

fn main() {
    for i in SimpleStepRange(0, 10, 2) {
        println!("{}", i);
    }
}

যদি এককে বিভিন্ন ধরণের একাধিক ব্যাপ্তি পুনরাবৃত্তি করতে হয় তবে কোডটি নীচে জেনেরিক করা যেতে পারে:

use std::ops::Add;

struct StepRange<T>(T, T, T)
    where for<'a> &'a T: Add<&'a T, Output = T>,
          T: PartialOrd,
          T: Clone;

impl<T> Iterator for StepRange<T>
    where for<'a> &'a T: Add<&'a T, Output = T>,
          T: PartialOrd,
          T: Clone
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.0 < self.1 {
            let v = self.0.clone();
            self.0 = &v + &self.2;
            Some(v)
        } else {
            None
        }
    }
}

fn main() {
    for i in StepRange(0u64, 10u64, 2u64) {
        println!("{}", i);
    }
}

যদি অসীম লুপের প্রয়োজন হয় তবে খোলার শেষ কাঠামো তৈরি করতে উপরের সীমানা চেকটি মুছে ফেলতে আমি এটি আপনার কাছে রেখে দেব ...

এই পদ্ধতির সুবিধা হ'ল এটি forচিনির সাথে কাজ করে এবং অস্থিতিশীল বৈশিষ্ট্যগুলি ব্যবহারযোগ্য হয়ে ওঠার পরেও কাজ চালিয়ে যাবে; এছাড়াও, স্ট্যান্ডার্ড Rangeগুলি ব্যবহার করে ডি-সুগারযুক্ত পদ্ধতির বিপরীতে , এটি একাধিক .next()কল করে দক্ষতা হারাবে না । অসুবিধাগুলি হ'ল এটিরেটর সেট আপ করতে কোডের কয়েক লাইন লাগে তাই কেবলমাত্র কোডের জন্য এটি উপযুক্ত হতে পারে যাতে প্রচুর লুপ থাকে।


অন্য ধরণের যোগ করে, Uআপনার দ্বিতীয় অপশনে আপনি এমন প্রকারগুলি ব্যবহার করতে পারেন যা বিভিন্ন ধরণের সাথে সংযোজন সমর্থন করে এবং এখনও একটি ফলন করে T। উদাহরণস্বরূপ সময় এবং সময়কাল মাথায় আসে।
রায়ান

@ রায়ান, এটি একটি ভাল ধারণা বলে মনে হচ্ছে এবং কাঠামোটি নীচে সংজ্ঞায়িত করে কাজ করা উচিত: <স্ট্র্যাঞ্জ <টি> (টি, টি, ইউ) যেখানে <'এ,' বি> এবং 'এ টি: যুক্ত <&' বি ইউ, আউটপুট = টি>, টি: আংশিক ওড়না, টি: ক্লোন; যা ইনপুট টি এবং ইউ ধরণের জন্য বিভিন্ন জীবনকালকে অনুমতি দেয়।
গর্ডনবিবুড


3

আপনি আপনার সি ++ কোড লিখবেন:

for (auto i = 0; i <= n; i += 2) {
    //...
}

... জং এর মত:

let mut i = 0;
while i <= n {
    // ...
    i += 2;
}

আমি মনে করি মরিচা সংস্করণটি আরও পঠনযোগ্য।


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

4
@ ডাব্লুডিএস যা continueসঠিকভাবে কাজ করার জন্য, ভাষাটির একটি প্রাথমিক বৈশিষ্ট্য পেতে প্রতিবিম্বিত ব্যস্ততার কাজ করে। যদিও এটি করা যায়, এই নকশাটি বাগগুলিকে উত্সাহ দেয়।
চই টি। রেক্স

2

আপনি যদি পূর্বনির্ধারিত কিছু এবং 2 এর মতো ছোট কিছু দিয়ে পদক্ষেপ নিচ্ছেন তবে আপনি নিজেই পদক্ষেপ নিতে পুনরুক্তি ব্যবহার করতে চাইতে পারেন। যেমন:

let mut iter = 1..10;
loop {
    match iter.next() {
        Some(x) => {
            println!("{}", x);
        },
        None => break,
    }
    iter.next();
}

এমনকি আপনি এটি একটি স্বেচ্ছাসেবী পরিমাণে পদক্ষেপে ব্যবহার করতে পারেন (যদিও এটি অবশ্যই হজম করতে দীর্ঘতর এবং কঠিন হচ্ছে):

let mut iter = 1..10;
let step = 4;
loop {
    match iter.next() {
        Some(x) => {
            println!("{}", x);
        },
        None => break,
    }
    for _ in 0..step-1 {
        iter.next();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.