Как разделить на основе 'в Rust - PullRequest
0 голосов
/ 02 мая 2020

Эта программа предназначена для проверки количества вхождений каждого слова в строке. Каждый тест прошел успешно, кроме случаев, когда words = "Joe can't tell between 'large' and large." или words = "First: don't laugh. Then: don't cry.". Если я избавлюсь от !c.is_alphanumeric() в разделенном замыкании, то мне придется написать каждый специальный символ, по которому нужно разделить слова.

Это упражнение для начинающих на упражнениях, поэтому я хотел избежать ящика регулярных выражений.

use std::collections::HashMap;

pub fn word_count(words: &str) -> HashMap<String, u32> {
    let mut indexes: HashMap<String, u32> = HashMap::new();
    let to_lowercase = words.to_lowercase();

    for c in to_lowercase.split(|c: char| !c.is_alphanumeric()).filter(|&x| x!="").collect::<Vec<&str>>(){


        let entry = indexes.entry(c.to_string()).or_insert(0);
        *entry += 1;
    };    

    indexes
}

Некоторые тесты

fn check_word_count(s: &str, pairs: &[(&str, u32)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<String, u32> = word_count(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.remove(&k.to_string()).unwrap_or(0)), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&String, &u32)>>(), vec![]);
}


fn with_apostrophes() {
    check_word_count(
        "First: don't laugh. Then: don't cry.",
        &[
            ("first", 1),
            ("don't", 2),
            ("laugh", 1),
            ("then", 1),
            ("cry", 1),
        ],
    );
}

#[test]
#[ignore]
fn with_quotations() {
    check_word_count(
        "Joe can't tell between 'large' and large.",
        &[
            ("joe", 1),
            ("can't", 1),
            ("tell", 1),
            ("between", 1),
            ("large", 2),
            ("and", 1),
        ],
    );
}


1 Ответ

1 голос
/ 02 мая 2020

Полагаю, это зависит от определения слова с точки зрения правил. Если вы просто включите одинарную кавычку ' в качестве одного из символов, которые не вызовут разбиения слов, то вы включите

  • все сокращения и
  • все слова, которые заключите их в кавычки (как отдельные типы слов)

Следующий код предотвращает разбиение на одинарные кавычки:

let single_quote: char = '\'';
....
split( |c: char| !c.is_alphanumeric() && c != single_quote)

Это будет означать 'large' как отдельное слово из large, что может быть не тем, что вы хотите, но, опять же, правила не ясны.

И вот моя полная программа.

use std::collections::HashMap;

pub fn word_count(words: &str) -> HashMap<String, u32> {
    let mut indexes: HashMap<String, u32> = HashMap::new();
    let to_lowercase = words.to_lowercase();
    let single_quote: char = '\'';

    for c in to_lowercase.split
    ( |c: char| !c.is_alphanumeric() && c != single_quote)
        .filter(|x| !x.is_empty())
        .collect::<Vec<&str>>(){

        let entry = indexes.entry(c.to_string()).or_insert(0);
        *entry += 1;
    };    

   indexes
}

fn main(){
    let phrase = "Joe can't tell between 'large' and large.";
    let indices = word_count(phrase);
    println!("Phrase: {}", phrase);
    for (word,index) in indices {
        println!("word: {}, count: {}", word, index);
    }
}

И вот вывод из моей функции main (). Дайте мне знать, если это поможет.

Phrase: Joe can't tell between 'large' and large.
word: joe, count: 1    
word: can't, count: 1  
word: 'large', count: 1
word: and, count: 1    
word: between, count: 1
word: tell, count: 1   
word: large, count: 1 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...