LINUX.ORG.RU

История изменений

Исправление red75prim, (текущая версия) :

Не буду убеждать в красоте кода. Но сразу видно, что код - кривоватый: лайфтайм 'a используется только в одном месте. Тот, кто писал, не совсем понимал, что делает.

Ну и можно написать немного понятнее. А так это - обычный функциональный pipeline.

pub fn closest_but_not_really<T>(
    choice: &str,
    iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    iter.map(|item| {
        let distance = lev_distance(choice, key(&item));
        (distance, item)
    })
    .min_by_key(|&(distance, _)| distance)
    .and_then(|(distance, item)| {
        if distance < 4 {
            Some(item)
        } else {
            None
        }
    })
}

Или можно написать в императивном стиле. Но тут больше возможностей сделать ошибку.

pub fn closest_less<T>(
    choice: &str,
    mut iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    let mut min_item = iter.next()?;
    let mut min_dist = lev_distance(choice, key(&min_item));
    for item in iter {
        let dist = lev_distance(choice, key(&item));
        if dist < min_dist {
            min_dist = dist;
            min_item = item;
        }
    }
    if min_dist < 4 {
        Some(min_item)
    } else {
        None
    }
}

Исправление red75prim, :

Не буду убеждать в красоте кода. Но сразу видно, что код - кривоватый: лайфтайм 'a используется только в одном месте. Тот, кто писал, не совсем понимал, что делает.

Ну и можно написать немного понятнее. А так это - обычный функциональный pipeline.

pub fn closest_but_not_really<T>(
    choice: &str,
    iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    iter.filter_map(|item| {
        let distance = lev_distance(choice, key(&item));
        if distance < 4 {
            Some((distance, item))
        } else {
            None
        }
    }) 
    .min_by_key(|&(distance, _)| distance)
    .map(|(_, item)| item)
}

Или можно написать в императивном стиле. Но тут больше возможностей сделать ошибку.

pub fn closest_less<T>(
    choice: &str,
    mut iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    let mut min_item = iter.next()?;
    let mut min_dist = lev_distance(choice, key(&min_item));
    for item in iter {
        let dist = lev_distance(choice, key(&item));
        if dist < min_dist {
            min_dist = dist;
            min_item = item;
        }
    }
    if min_dist < 4 {
        Some(min_item)
    } else {
        None
    }
}

Исходная версия red75prim, :

Не буду убеждать в красоте кода. Но сразу видно, что код - кривоватый: лайфтайм 'a используется только в одном месте. Тот, кто писал не совсем понимал, что делает.

Ну и можно написать немного понятнее. А так это - обычный функциональный pipeline.

pub fn closest_but_not_really<T>(
    choice: &str,
    iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    iter.filter_map(|item| {
        let distance = lev_distance(choice, key(&item));
        if distance < 4 {
            Some((distance, item))
        } else {
            None
        }
    }) 
    .min_by_key(|&(distance, _)| distance)
    .map(|(_, item)| item)
}

Или можно написать в императивном стиле. Но тут больше возможностей сделать ошибку.

pub fn closest_less<T>(
    choice: &str,
    mut iter: impl Iterator<Item = T>,
    key: impl Fn(&T) -> &str,
) -> Option<T> {
    let mut min_item = iter.next()?;
    let mut min_dist = lev_distance(choice, key(&min_item));
    for item in iter {
        let dist = lev_distance(choice, key(&item));
        if dist < min_dist {
            min_dist = dist;
            min_item = item;
        }
    }
    if min_dist < 4 {
        Some(min_item)
    } else {
        None
    }
}