2014-07-17 8 views
7

क्या जंगलों में कई श्रेणियों या पुनरावृत्तियों के "उत्पाद" पर पुनरावृत्ति करने का कोई प्राकृतिक तरीका है?कई श्रेणियों या पुनरावृत्तियों के उत्पाद पर पुनरावृत्ति कैसे करें?

यह तब आता है जब आप एक बहुआयामी सरणी, या शायद कुछ राज्य स्थान पर पुनरावृत्त कर रहे हैं। उदाहरण के लिए, मैं 5 तत्वों के साथ एक बूलियन ट्यूपल के सभी संभावित मूल्यों पर विचार करना चाहता हूं। नेस्टिंग 5 for लूप थोड़ा अनावश्यक है।

+1

मुझे लगता है कि मैं बूल को एक विशेष मामला होने की उम्मीद करता हूं, मैं एक अलग उपकरण चाहता हूं। लेकिन एक सामान्य व्यक्ति अन्य परिस्थितियों के लिए आसान होगा। असल में, बूल के लिए, कई लोग 'std :: bitset' पर "पुनरावृत्ति" (गिनती) करते हैं। –

+0

पायथन में आप क्या चाहते हैं ['itertools.product'] (https://docs.python.org/3/library/itertools.html#itertools.product)। जंग में ऐसी चीज को कार्यान्वित करना, हालांकि, उतना आसान नहीं है जितना कि यह पहले प्रतीत होता है। इसे लागू करने के लिए आम तौर पर मैक्रोज़ की आवश्यकता होगी। –

उत्तर

7

यहाँ एक मैक्रो काम करता है:

#![feature(macro_rules)] 

macro_rules! product(
    ($first:ident, $($next:ident),*) => (
     $first.iter() $(
      .flat_map(|e| std::iter::Repeat::new(e) 
       .zip($next.iter())) 
     )* 
    ); 
) 

fn main() { 
    let a = ['A', 'B', 'C']; 
    let b = [1i, 4]; 
    let c = [true, false]; 
    let d = ['x', 'y']; 

    for (((a, b), c), d) in product![a, b, c, d] { 
     println!("{} {} {} {}", a, b, c, d); 
    } 
} 

आउटपुट:

A 1 true x 
A 1 true y 
A 1 false x 
A 1 false y 
A 4 true x 
A 4 true y 
etc... 

Playpen example

मैक्रो निम्नलिखित

a.iter() 
    .flat_map(|e| std::iter::Repeat::new(e).zip(b.iter())) 
    .flat_map(|e| std::iter::Repeat::new(e).zip(c.iter())) 
    .flat_map(|e| std::iter::Repeat::new(e).zip(d.iter())) 

के लिए विस्तारितइटरेटर के अनुक्रम को एक पुनरावर्तक में जोड़ता है। e एक इटरेटर द्वारा उत्पादित एक तत्व है।

std::iter::Repeat::new(e) एक पुनरावर्तक बनाता है जो e दोहराता है।

.zip(...) एक साथ दो पुनरावृत्तियों को दोहराता है, जो एक जोड़ी दोनों के तत्वों को उपज देता है।

मैक्रो थोड़ा अधिक समय की व्याख्या करने के हैं, इसलिए इसे पढ़ने के लिए macro guide

मैं अगर यह यह करने के लिए सबसे अच्छा तरीका है पता नहीं है सबसे अच्छा है।

+1

धन्यवाद, लेकिन क्या आप यह बता सकते हैं कि यह क्या करता है? (वाक्यविन्यास नहीं, केवल मूल तकनीक।) मैं जंग के लिए बेहद नया हूं, और प्रतिलिपि/पेस्ट के बजाय सीखना चाहता हूं। :) – starwed

+0

@starwed किया, उम्मीद है कि यह अब स्पष्ट है। –

+4

यह ध्यान देने योग्य है कि यह 'ए' के प्रत्येक तत्व के लिए 'बी' पुनरावर्तक' और' 'बी 'आदि में तत्वों की प्रत्येक जोड़ी के लिए' सी' इटरेटर 'को पुन: प्रयास करता है, इसलिए यदि इनमें से कोई भी मूल्य का उपभोग करता है, या महंगी हैं, या केवल एक बार बुलाया जाना चाहिए, तो यह रणनीति आवश्यक रूप से वांछित के रूप में काम नहीं करता है। (हालांकि, सामान्य रूप से इस तरह के उत्पादकों को उत्पाद वास्तव में संभव नहीं है, कम से कम, बिना किसी माध्यमिक डेटा संरचना को इकट्ठा किए बिना, 'वीईसी', और मुझे लगता है कि अधिकतर इटरेटर बनाने के लिए सस्ते हैं, इसलिए ये प्रतीत नहीं होते हैं विशेष रूप से समस्याग्रस्त।) – huon

3

itertools crate में इटरेटर के उत्पाद पर पुनरावृत्ति के लिए एक बहुत ही एर्गोनोमिक मैक्रो (iproduct!) है। यहां एक उदाहरण दिया गया है:

#[macro_use] 
extern crate itertools; 

pub fn main() { 
    let a = ['A', 'B', 'C']; 
    let b = [1, 4]; 
    let c = [true, false]; 
    let d = ['x', 'y']; 

    for (a, b, c, d) in iproduct!(&a, &b, &c, &d) { 
     println!("{} {} {} {}", a, b, c, d); 
    } 
} 
+0

'itertools' में [' cartesian_product' फ़ंक्शन] (https://bluss.github.io/rust-itertools/doc/itertools/trait.Itertools.html#method.cartesian_product) भी है। –

संबंधित मुद्दे

 संबंधित मुद्दे