Loop and modify the array?

#[derive(Debug, PartialEq)]
struct AreaCodeIndex {
    code: String,
    childs: Vec<AreaCodeIndex>,
}
fn main() {
    let code_str = vec![vec!["aa", "bb"], vec!["aa", "cc"]];
    let mut code_area_data: Vec<AreaCodeIndex> = vec![];
    for tmp in code_str {
        let mut pe_ref = &mut code_area_data; //默认指向 code_area_data
        for tt in tmp {
            pe_ref = if let Some(i) = pe_ref.iter().position(|tc| tc.code == *tt) {
                &mut pe_ref[i].childs
            } else {
                pe_ref.push(AreaCodeIndex {
                    code: tt.to_owned(),
                    childs: vec![],
                });
                &mut pe_ref.last_mut().unwrap().childs
            };
        }
    }
    println!("{:?}", code_area_data);
}

Without more context about what you are trying to achieve, it will be improbable that we will be able to help you effectively. None of us can read minds (I assume).

Given your snippet and the comment with the structure you want to create, how about using HashMaps instead of Vecs? The algorithm for what I think you want to create (your test case is very generic and again lacks any explanation) becomes a lot simpler and more effective with a data structure that does not require iteration for doing lookups and insertions. So here my solution, though again I have to emphasize the lack of information you provided:

use std::collections::HashMap;

#[derive(Debug, PartialEq)]
struct AreaCodeIndex {
    code: String,
    childs: HashMap<String, AreaCodeIndex>,
}

fn main() {
    let code_str = vec![vec!["aa", "bb"], vec!["aa", "cc"]];

    let mut code_area_data: HashMap<String, AreaCodeIndex> = HashMap::new();

    for pair in code_str {
        let key = pair[0];
        let value = pair[1];

        code_area_data
            .entry(key.to_owned())
            .and_modify(|index| {
                index
                    .childs
                    .entry(value.to_owned())
                    .or_insert(AreaCodeIndex {
                        code: value.to_owned(),
                        childs: HashMap::new(),
                    });
            })
            .or_insert(AreaCodeIndex {
                code: key.to_owned(),
                childs: HashMap::from_iter([(
                    value.to_owned(),
                    AreaCodeIndex {
                        code: value.to_owned(),
                        childs: HashMap::new(),
                    },
                )]),
            });
    }

    assert_eq!(
        code_area_data,
        HashMap::from_iter([(
            "aa".to_owned(),
            AreaCodeIndex {
                code: "aa".to_owned(),
                childs: HashMap::from_iter([
                    (
                        "bb".to_owned(),
                        AreaCodeIndex {
                            code: "bb".to_owned(),
                            childs: HashMap::new(),
                        }
                    ),
                    (
                        "cc".to_owned(),
                        AreaCodeIndex {
                            code: "cc".to_owned(),
                            childs: HashMap::new(),
                        }
                    )
                ])
            }
        )])
    );
}

Playground.

1 Like

I expect code_area_data the result to be:

AreaCodeIndex {
            code: "aa".to_string(),
            childs: vec![
                AreaCodeIndex {
                    code: "bb".to_string(),
                    childs: vec![],
                },
                AreaCodeIndex {
                    code: "bb".to_string(),
                    childs: vec![],
                },
            ],
        }

code_str has a lot of data, for the example I just wrote a part of it.

Since code_str has a large amount of data, need to use traversal

for tmp in code_str.iter_mut() {
while ... { ...}
}

I found the answer: rust - How to find or insert into a Vec - Stack Overflow
Thank you for reply

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.