1

Тема: Наступний елемент в BTreeMap

Потрібно отримати наступний елемент в BTreeMap.
Намагаюся отримати його ось таким чином:

  let next_word = word_indexes.range((Bound::Excluded(word), Bound::Unbounded)).next();

Але отримую помилку:

let next_word = word_indexes.range((Bound::Excluded(word), Bound::Unbounded)).next();
    |                                              ^^^^^ cannot infer type of the type parameter `T` declared on the method `range`
    |
    = note: multiple `impl`s satisfying `std::string::String: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl Borrow<str> for std::string::String;
            - impl<T> Borrow<T> for T
              where T: ?Sized;
note: required by a bound in `BTreeMap::<K, V, A>::range`
   --> /usr/src/debug/rust/rustc-1.78.0-src/library/alloc/src/collections/btree/map.rs:1205:5
help: consider specifying the generic arguments
    |
626 |                 let next_word = word_indexes.range::<T, (std::collections::Bound<&std::string::String>, std::collections::Bound<T>)>((Bound::Excluded(word), Bound::Unbounded)).next();

Розумію, що треба дописати, що пропонує компілятор,
але не розумію, що він має на увазі під типом Т?
BTreeMap складається з <String, (usize, usize)>.
Чи є простіший спосіб отримання наступного елемента в BTreeMap?

2

Re: Наступний елемент в BTreeMap

Ось це працює:

let next_word = word_indexes.range::<String, (std::collections::Bound<&std::string::String>, 
                    std::collections::Bound<&String>)> ((Bound::Excluded(word), Bound::Unbounded)).next();
Подякували: leofun011

3

Re: Наступний елемент в BTreeMap

Визначення range:

pub fn range<T, R>(&self, range: R) -> Range<'_, K, V> ⓘ
where
    T: Ord + ?Sized,
    K: Borrow<T> + Ord,
    R: RangeBounds<T>,

Звертаю увагу: компілятор не зумів вивести лише T. R він виводить. Відповідно, можна записати

let next_word = word_indexes.range::<String, _> ((Bound::Excluded(word), Bound::Unbounded)).next();

Але підозрюю, що це проблема XY. Що саме ви намагаєтеся зробити?

Подякували: Teg Miles, leofun012

4 Востаннє редагувалося Teg Miles (16.05.2024 21:42:24)

Re: Наступний елемент в BTreeMap

Ваш варіант теж працює.
Я порівнюю введене в пошук слово з ключем зі згаданого BTreeMap.
Ключ BTreeMap — це слово зі словника, значення BTreeMap — це т'юпл з початком і кінцем слова в словнику,
який, по суті, є одним великим String.
Далі беру початок слова-ключа і початок наступного за ним слова(або до кінця словника, якщо наступного слова немає),
а тоді вирізаю потрібну мені статтю словника, що знаходиться між ними.
Ця стаття потім показується користувачу у відповідному вікні програми.

5

Re: Наступний елемент в BTreeMap

Якщо так?

let next_word = word_indexes.range(word..)
                            .skip(1)
                            .next();

А, ні, вам реально треба excluded...

6

Re: Наступний елемент в BTreeMap

Замінив BTreeMap на IndexMap з крейту indexmap і зробив ось так:

fn get_raw_article(word_lower: &String,
    dict_indexes: &Rc<RefCell<HashMap<String, DictTuple>>>) -> (String, String){

    let mut raw_article: String = Default::default();
    let mut dict_title: String = Default::default();
    for (dict_name, (_, _, _, dict_body, word_indexes))
        in &*dict_indexes.borrow(){
        for index in 0..word_indexes.len(){
            let (word, (word_start, _)) =
                word_indexes.get_index(index).expect("Can't get DictTuple.");
            if word.to_lowercase() == word_lower.to_string(){
               dict_title = dict_name.to_string();
               if index != (word_indexes.len() - 1){
                   let (_, (next_word_start, _)) = word_indexes
                       .get_index(index+1)
                       .expect("Can't get DictTuple.");
                    raw_article = dict_body.get(**word_start..**next_word_start)
                     .expect("Can't get substring").to_string();
                }
               else{
                   raw_article = dict_body.get(**word_start..)
                       .expect("Can't get substring").to_string();
                }
            }
        }
    }

    (dict_title, raw_article)
}

По суті, стежу за індексом, якщо дорівнює останньому — одна дія, якщо ні — інша.
Головне елементи лишаються в тому порядку, в якому їх додавали до IndexMap.
І не треба лізти по наступний елемент BTreeMap, що саме знаходиться в циклі.