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

use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;

fn main() {
    let rand_string: String = thread_rng()
        .sample_iter(&Alphanumeric)
        .take(30)
        .collect();

    println!("{}", rand_string);
}

कोड का यह टुकड़ा हालांकि संकलित नहीं करता है, (नोट: मैं रात में हूं):

error[E0277]: a value of type `String` cannot be built from an iterator over elements of type `u8`
 --> src/main.rs:8:10
  |
8 |         .collect();
  |          ^^^^^^^ value of type `String` cannot be built from `std::iter::Iterator<Item=u8>`
  |
  = help: the trait `FromIterator<u8>` is not implemented for `String`

ठीक है, उत्पन्न होने वाले तत्व u8 प्रकार के हैं। तो मुझे लगता है कि यह एक सरणी या वेक्टर है u8:

use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;

fn main() {
    let r = thread_rng()
        .sample_iter(&Alphanumeric)
        .take(30)
        .collect::<Vec<_>>();
    let s = String::from_utf8_lossy(&r);
    println!("{}", s);
}

और यह संकलित और काम करता है!

2dCsTqoNUR1f0EzRV60IiuHlaM4TfK

सब ठीक है, सिवाय इसके कि मैं पूछना चाहता हूं कि क्या कोई बता सकता है कि वास्तव में प्रकारों के बारे में क्या होता है और इसे कैसे अनुकूलित किया जा सकता है।

प्रश्न

  1. .sample_iter(&Alphanumeric) u8 का उत्पादन करता है और chars का नहीं?
  2. मैं दूसरे चर s से कैसे बच सकता हूं और सीधे u8 को utf-8 वर्ण के रूप में व्याख्या कर सकता हूं? मुझे लगता है कि स्मृति में प्रतिनिधित्व बिल्कुल नहीं बदलेगा?
  3. इन तारों की लंबाई हमेशा 30 होनी चाहिए। मैं Vec दूर के ढेर आवंटन को कैसे अनुकूलित कर सकता हूं? इसके अलावा वे वास्तव में String के बजाय char[] हो सकते हैं।
1
dani 28 पद 2020, 16:33

2 जवाब

सबसे बढ़िया उत्तर

.sample_iter(&Alphanumeric) u8 उत्पन्न करता है न कि वर्ण?

हां, इसे रैंड v0.8.1 में बदल दिया गया था। आप 0.7.3 के लिए डॉक्स में देख सकते हैं :

impl Distribution<char> for Alphanumeric

लेकिन फिर 0.8.0 के लिए डॉक्स में:

impl Distribution<u8> for Alphanumeric

मैं दूसरे चर s से कैसे बच सकता हूं और सीधे u8 को utf-8 वर्ण के रूप में व्याख्या कर सकता हूं? मुझे लगता है कि स्मृति में प्रतिनिधित्व बिल्कुल नहीं बदलेगा?

ऐसा करने के कुछ तरीके हैं, सबसे स्पष्ट है कि प्रत्येक u8 को एक char में डाला जाए:

let s: String = thread_rng()
    .sample_iter(&Alphanumeric)
    .take(30)
    .map(|x| x as char)
    .collect();

या, From<u8> इंस्टेंस का इस्तेमाल करके char का:

let s: String = thread_rng()
    .sample_iter(&Alphanumeric)
    .take(30)
    .map(char::from)
    .collect();

बेशक यहां, चूंकि आप जानते हैं कि प्रत्येक u8 मान्य UTF-8 होना चाहिए, आप String::from_utf8_unchecked, जो from_utf8_lossy से तेज है (हालांकि शायद as char मेथड के समान स्पीड के आसपास):

let s = unsafe {
    String::from_utf8_unchecked(
        thread_rng()
            .sample_iter(&Alphanumeric)
            .take(30)
            .collect::<Vec<_>>(),
    )
};

अगर, किसी कारण से, unsafe आपको परेशान करता है और आप सुरक्षित रहना चाहते हैं, तो आप धीमे String::from_utf8 और unwrap Result ताकि आपको UB के बजाय घबराहट हो (भले ही कोड चाहिए कभी भी घबराएं या यूबी):

let s = String::from_utf8(
    thread_rng()
        .sample_iter(&Alphanumeric)
        .take(30)
        .collect::<Vec<_>>(),
).unwrap();

इन तारों की लंबाई हमेशा 30 होनी चाहिए। मैं Vec दूर के ढेर आवंटन को कैसे अनुकूलित कर सकता हूं? इसके अलावा वे वास्तव में स्ट्रिंग्स के बजाय char[] हो सकते हैं।

सबसे पहले, मेरा विश्वास करो, आप वर्णों के सरणी नहीं चाहते हैं। उनके साथ काम करने में मजा नहीं आता। यदि आप एक स्टैक स्ट्रिंग चाहते हैं, तो एक u8 सरणी है, फिर std::str::from_utf8 या तेज़ std::str::from_utf8_unchecked (फिर से केवल प्रयोग करने योग्य क्योंकि आप जानते हैं कि मान्य utf8 जनरेट किया जाएगा।)

ढेर आवंटन को अनुकूलित करने के लिए, यह उत्तर देखें। मूल रूप से, यह कुछ हैकनेस/कुरूपता के साथ संभव नहीं है (जैसे कि अपना स्वयं का फ़ंक्शन बनाना जो एक इटरेटर को 30 तत्वों की सरणी में एकत्र करता है)।

एक बार कॉन्स्ट जेनरिक के स्थिर हो जाने के बाद, एक बहुत सुंदर समाधान।

1
Aplet123 28 पद 2020, 18:09

{a href="https://docs.rs/rand/0.8.0/rand/distributions/struct.Alphanumeric.html#example" rel="nofollow noreferrer">दस्तावेज़ में पहला उदाहरण के लिए rand::distributions::Alphanumeric दर्शाता है कि यदि आप u8s को chars में बदलना चाहते हैं, तो आपको char::from फ़ंक्शन का उपयोग करके उन्हें map करना चाहिए:

use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;

fn main() {
    let rand_string: String = thread_rng()
        .sample_iter(&Alphanumeric)
        .map(char::from) // map added here
        .take(30)
        .collect();

    println!("{}", rand_string);
}

खेल का मैदान

1
pretzelhammer 28 पद 2020, 16:40