#[Solved] String iter into &str iter

29 messages · Page 1 of 1 (latest)

pale quartz
#

Hello there I am struggling a bit here with an AOC problem, the thing is that to read from a file I get an String but in order to use a Regex I need an &str. This is as far as I have reach right know I'm not really sure how to continue I have tried a few things but without any luck.

use std::env;

use anyhow::Context;
use aoc_common::load_input;
use regex::Regex;

fn main() -> anyhow::Result<()> {
    let lines = load_input(env::args())
        .expect("Unable to load input")
        .map(|line| &*line) // <<<< The problem is here, since I can't borrow line and then return :/ 
        .collect::<Vec<_>>();

    let solution_p1: u16 = lines.clone().into_iter().get_solution_p1()?;

    println!("Solution P1: {solution_p1}");

    Ok(())
}

pub trait AOC {
    fn get_solution_p1(self) -> anyhow::Result<u16>;
}

impl<'a, T: Iterator<Item = &'a str>> AOC for T {
    fn get_solution_p1(self) -> anyhow::Result<u16> {
        let game_regex = Regex::new(r"Game (\d+):")?;
        self.map(|line| line).map(|line| {
            game_regex
                .captures(line)
                .context("Unable to capture line using regex")
        });
        Ok(0)
    }
}
cedar fossil
#

Does .captures(&line) work?
Also, the first map doesn't do anything.

pale quartz
#

oh yeah ignore that first me that's just some leftover from my attempts

cedar fossil
#

Wait, why are you implementing a trait for every type?????

pale quartz
#

no no, the trait is just for String//&str just to "extend" the method in main

cedar fossil
#

Oh, it's just for iterators.
Why though?

#

Is there a reason that get_solution_p1 can't be a normal generic method that accepts a normal prameter?

pale quartz
pale quartz
#

do you think that is the cause?

cedar fossil
#

I don't think it's the cause. But still, it looks really weird to me.

#

What's the error in your current initial code?

#

Oh, sorry, my brain isn't working.

pale quartz
cedar fossil
#

You should store lines as a Vec<String>`, so you own the strings, so the strings won't be dropped until you're done using them.

#

To create an iterator over &str out of a Vec<String>, write lines.iter().map(|s| s.as_str())

#

Also, I recommend checking out the tap crate if you prefer the method chaining style of code.

pale quartz
#

hmmm so maybe then the Iterator may be the cause of all my issues here?

#

let me try that rn

#

ok so what you suggested helped me to solve everything my problem is exactly as the problem said I suppose the way to fix it is to iterate over &String rather than String

#

this is the final working code

use std::env;

use anyhow::Context;
use aoc_common::load_input;
use regex::Regex;

fn main() -> anyhow::Result<()> {
    let lines = load_input(env::args())
        .expect("Unable to load input")
        .collect::<Vec<_>>();

    let solution_p1: u16 = lines.clone().iter().get_solution_p1()?;

    println!("Solution P1: {solution_p1}");

    Ok(())
}
pub trait AOC {
    fn get_solution_p1(self) -> anyhow::Result<u16>;
}

impl<'a, T: Iterator<Item = &'a String>> AOC for T {
    fn get_solution_p1(self) -> anyhow::Result<u16> {
        let game_regex = Regex::new(r"Game (\d+):")?;
        self.map(|line| {
            game_regex
                .captures(&line)
                .context("Unable to capture line using regex")
        });
        Ok(0)
    }
}
cedar fossil
#

The key thing that the vec has to own the strings. You can iterate over &str if you want

pale quartz
#

but I don't understand why in this case borrow the string is the solution

cedar fossil
#

lines.iter().map(|s| s.as_str()).get_solution_p1() would work with the Item=&'a str version

#

Also, try running clippy on your code.

#

cargo clippy

pale quartz
#

my problem is that I just run clippy at the end xD

cedar fossil
#

That's fine

pale quartz
#

ok thank you for you help everything is solved now!!