【问题标题】:How to Filter out a Vec of Strings From a Vec of Structs Rust如何从结构体的 Vec 中过滤出字符串的 Vec Rust
【发布时间】:2022-06-11 03:31:23
【问题描述】:

与结构的向量相比,我有一个有效的解决方案来过滤掉字符串的输入 vec。但是,我的代码看起来很复杂,我尝试使用 iter::filter(https://doc.rust-lang.org/stable/std/iter/struct.Filter.html) 简化代码。这会导致问题,因为迭代器返回的值是引用并且不能直接使用。看来我对 iter 的理解以及在 structs 向量中可以做什么需要刷新。以下是有效的简化过滤代码:

#[derive(Debug)]
pub struct Widget {
    name: String,
    pin: u16,
}

impl Widget{
    pub fn new(widget_name: String, widget_pin: String) -> Widget {
        let widget_pin_u16 = widget_pin.parse::<u16>().expect("Unable to parse");
        let nw = Widget {
            name: widget_name,
            pin: widget_pin_u16
        };
        return nw
    }
}

pub struct WidgetHolder {
    widgets: Vec<Widget>,
    widget_holder_name: String
}

impl WidgetHolder {
    fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
        let mut widgets_to_add: Vec<String> = Vec::new();
        for widget in valid_widgets_found {
            // The string musy be compared to pin field, so we're converting
            let widget_offset = widget
                .clone()
                .parse::<u16>()
                .expect("Unable to parse widget base into int.");
            // If it doesnt exist in our widgetHolder widgets vector, then lets add it.
            let mut widget_exists = false;
            for existing_widget in &self.widgets {
                if widget_offset == existing_widget.pin {
                    widget_exists = true;
                    break;
                }
            }
            if !widget_exists {
                widgets_to_add.push(widget.clone());
            }
        }
        
        if widgets_to_add.is_empty() {
            return;
        }
        
        for widget in widgets_to_add {
            let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
            self.widgets.push(loaded_widget);
        }
    }
}


pub fn main() {
    let init_vec = Vec::new();
    let mut wh = WidgetHolder {
        widgets: init_vec,
        widget_holder_name: "MyWidget".to_string()
    };
    let vec1 = vec!["1".to_string(), "2".to_string(), "3".to_string()];
    wh.add_widgets(vec1);
    println!("{:?}", wh.widgets);

    let vec2 = vec!["2".to_string(), "3".to_string(), "4".to_string()];
    wh.add_widgets(vec2);
    println!("{:?}", wh.widgets);
}

有没有一种方法可以清理这段代码而不必使用这么多的数据结构和循环?过滤器 api 看起来很干净,但它是否适用于我试图变异(附加到它)的结构内的向量?

编辑 在尝试获取堆栈跟踪后,我实际上让过滤器工作了......


    fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
        let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
                .filter(|widget_pin| {
                    let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
                    let mut widget_exists = false;
                    for existing_widget in &self.widgets {
                        if widget_offset == existing_widget.pin {
                            widget_exists = true;
                            break;
                        }
                    }
                    !widget_exists
                })
                .collect();
        
        if widgets_to_add.is_empty() {
            return;
        }
        
        for widget in widgets_to_add {
            let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
            self.widgets.push(loaded_widget);
        }
    }

【问题讨论】:

  • 你对filter()的尝试是什么?您遇到了哪些错误(来自cargo check 的完整错误)?
  • 另外,请创建一个 Minimal 可重现的示例。最好是我们可以在操场上跑的东西。
  • 此代码缺少几个依赖项,例如widget::load_widget() 和WidgetHolder::directory。另外,此方法必须采用&amp;mut self,因为它试图推送到self.widgets。
  • @ChayimFriedman 示例已更新为可运行。立即获取过滤器堆栈跟踪。

标签: filter rust struct


【解决方案1】:

我想出了答案。当我最初尝试它时,它似乎是一个语法错误。对于将来寻找过滤器示例的任何人:


    fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
        let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
                .filter(|widget_pin| {
                    let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
                    let mut widget_exists = false;
                    for existing_widget in &self.widgets {
                        if widget_offset == existing_widget.pin {
                            widget_exists = true;
                            break;
                        }
                    }
                    !widget_exists
                })
                .collect();
        
        if widgets_to_add.is_empty() {
            return;
        }
        
        for widget in widgets_to_add {
            let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
            self.widgets.push(loaded_widget);
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多