V.iter().max() and getting non-value

v.iter().max() gives me max value of v.

Is it possible to get max .len() (length of element, not value) on fly ?

You can map to the length, then get the max of that.

2 Likes

There's max_by_key() that allows you to select by something different than the value returned (in case max_by_key complains about lifetimes, there's also max_by that works in more cases).

1 Like

I will try, thanks

Thank you.

I studied it, indeed, map works fine. It is new knowledge for me. Thx.

let my_col:usize =  v.iter().map(|f|f.len()).max() ;

Unfortunately, my vector appeared to be not simple vector .
It unexpectedly had generated 2 crazy errors. (crazy for me)
It is vector of tuple

v:Vec<(String,IpAddr) >

I blindly changed my iter (at least no compiler errors)

let my_col : usize  = v.iter().map(     |x:&  ( String, IpAddr  )   |    x.0 .len()     ).max() ;  

And then, vector returns Option! (crazy Option!!!!!!)
Here is my last version:

let my_col:Option<usize> /* : usize */=  v.iter().map( /* Some(  */     | col:&  ( String, IpAddr  )   |    col.0 .len()     ).max() ;  //   ) 30   
let my_col : usize   =    match my_col {
        Some( col )  =>  col ,
        None => 30 ,
};

Is that correct way to extract from Option what I need?

And now there are no errors, but.. ! This construction gives me very big digit. It seems takes max(string) and max(IpAdrr) together in sum. Or it is because of utf8..

. . . . . . . . . . . . . .
v is my_network_interfaces from local-ip-address = "0.4.4", if it does matter

And then, vector returns Option! (crazy Option!!!!!!)

The Option comes from the max function and it only happens if the vector is empty, since there isn't a max value then (there's no values!), it has to return None.
If you know, absolutely-for-sure your vector is never empty you can call unwrap:

let my_col: usize =  v.iter().map(|f|f.len()).max().unwrap() ;

This will return the value stored in the option, but if the option is None, it panics.
So, usually it's better not to unwrap. Instead you can you use a match statement like you did (perfectly fine), but in this case you could use a built-in-function instead:

let my_col: usize = my_col.unwrap_or(30);

unwrap_or returns the value if it exists (equivalent to Some(col) => col), or the value you pass into the function if it doesn't (equivalent to None => 30). It's just a shorthand for the match statement you wrote, since it's a very common thing to do.

This construction gives me very big digit. It seems takes max(string) and max(IpAdrr) together in sum

I'm not entirely sure what strings are being stored in your vec, but from the code you posted, it should be fine. x.0.len() should just be the length of the string.
If you post more context I can take a closer look, but that should be fine.

What if you check the actual value with:

println!("{}", v[my_col].0)

This should print the string to see how long it actually is.

1 Like

my_col is width of column for printline()

 println!("{}{:.<my_col$} {}" , ....

IpAddr is Ip, String is ethernet adapter name

my_col is 57, and taken using max() manipulations

57
ip6 Internet Connection...................................... fe80::d05e:2546:83ce:b785
ip4 Internet Connection...................................... 169.254.165.149
ip4 Local Area Connection 2.................................. 215.55.192.129
ip6 Loopback Pseudo-Interface 1.............................. ::1
ip4 Loopback Pseudo-Interface 1.............................. 127.0.0.1
ip4 VPN - VPN Client......................................... 169.254.143.27
ip4 ProtonVPN TUN............................................ 169.254.67.73
ip4 VirtualBox Host-Only Network............................. 192.168.56.1
ip4 Ethernet................................................. 10.129.11.233
ip4 outline-tap0............................................. 10.0.85.2
ip4 outline-tap0............................................. 169.254.16.63

my_col is 30, assigned manually

ip6 Internet Connection........... fe80::d05e:2546:83ce:b785
ip4 Internet Connection........... 169.254.165.149
ip4 Local Area Connection 2....... 215.55.192.129
ip6 Loopback Pseudo-Interface 1... ::1
ip4 Loopback Pseudo-Interface 1... 127.0.0.1
ip4 VPN - VPN Client.............. 169.254.143.27
ip4 ProtonVPN TUN................. 169.254.67.73
ip4 VirtualBox Host-Only Network.. 192.168.56.1
ip4 Ethernet...................... 10.129.11.233
ip4 outline-tap0.................. 10.0.85.2
ip4 outline-tap0.................. 169.254.16.63

Okay I see, in this case it's safer not to use len(). len returns you the number of bytes in the string, what you really want is the number of characters in the string:

my_string.chars().count()

Note that even this won't always behave how you expect it to. For more complex characters, what you really want to count is grapheme clusters, although that's probably overkill for terminal output here.

There's also a possibility that's there's padding in the string, depending on how you're getting it. So it might be worth trying:

my_string.trim().chars().count()

This will remove any leading and trailing whitespace. Hopefully one of these fixes the extra length you're seeing in your adapter names.

1 Like

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.