मैं कस्टम सीमा के साथ किसी श्रेणी पर कैसे पुनरावृति कर सकता हूं?


100

मैं 1 से एक कदम के साथ जंग में एक सीमा पर पुनरावृति कैसे कर सकता हूं? मैं C ++ बैकग्राउंड से आ रहा हूं इसलिए मैं कुछ ऐसा करना चाहूंगा

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 बिट चरण का समर्थन नहीं करेगी।
user202729

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और अस्थिर सुविधाओं के उपयोग योग्य होने पर भी काम करना जारी रखेगा; इसके अलावा, मानक Ranges का उपयोग करते हुए डी-शर्करा वाले दृष्टिकोण के विपरीत , यह कई .next()कॉलों द्वारा दक्षता नहीं खोता है । नुकसान यह है कि इटेरेटर सेट करने के लिए कोड की कुछ पंक्तियां लगती हैं इसलिए केवल कोड के लिए इसके लायक हो सकता है जिसमें बहुत सारे लूप हों।


Uअपने दूसरे विकल्प में एक और प्रकार जोड़कर, आप उन प्रकारों का उपयोग कर सकते हैं जो एक अलग प्रकार के साथ समर्थन करते हैं और फिर भी उपज देते हैं T। उदाहरण के लिए समय और अवधि दिमाग में आती है।
रयान

@Ryan, जो एक अच्छे विचार की तरह लगता है और इस प्रकार परिभाषित की गई संरचना के साथ काम करना चाहिए: संरचनात्मक StepRange <T> (T, T, U) जहां <'a,' b> & 'a T: Add <&' बी यू, आउटपुट = टी>, टी: आंशिक, टी: क्लोन; जो इनपुट टी और यू प्रकार के लिए अलग-अलग जीवनकाल की अनुमति देनी चाहिए।
गॉर्डनबूड


3

आप अपना C ++ कोड लिखेंगे:

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

... जैसे जंग में:

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

मुझे लगता है कि जंग संस्करण अधिक पठनीय है।


पुन: "जारी" को लूप में सम्मिलित करते हुए, कोई केवल एक सशर्त शाखा के अंदर भी संरचना के लिए ऐसा करेगा, मुझे लगता है। यदि ऐसा है, तो मुझे लगता है कि "जारी रखने" से पहले संरचना में सशर्त शाखा के अंदर वृद्धि करना ठीक होगा, और फिर यह इरादा के अनुसार काम करेगा। या मैं कुछ देख रहा हूँ?
WDS

1
@ भाषा की मूल विशेषता पाने के लिए, 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();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.