如何在Rust中按字符对字符串向量进行排序?

huangapple go评论56阅读模式
英文:

How to sort a vector of strings by char in Rust?

问题

The more idiomatic way to sort a vector of strings by char in Rust is to use the sort_by method with a custom comparator. Here's how you can achieve the desired output:

let mut vec = vec!["3r", "2n", "2s", "7r", "1s", "1s", "6r", "1s", "1n", "1n", "5n", "9n", "3r"];

vec.sort_by(|a, b| {
    let (a1, a2) = a.chars().collect::<Vec<_>>().split_at(1);
    let (b1, b2) = b.chars().collect::<Vec<_>>().split_at(1);
    
    a2.cmp(b2).then(a1.cmp(b1))
});

println!("{:?}", vec);

This code will sort the vector first by the second character of each string and then by the first character, giving you the desired output.

英文:

What is the more idiomatic way to sort a vector of strings by char?
Example:

Input:
[&quot;3r&quot;, &quot;2n&quot;, &quot;2s&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;6r&quot;, &quot;1s&quot;, &quot;1n&quot;, &quot;1n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;]
Desired output:
[&quot;1n&quot;, &quot;1n&quot;, &quot;2n&quot;, &quot;5n&quot;, &quot;9n, &quot;3r&quot;, &quot;3r&quot;, &quot;6r&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;2s&quot;]

First they need to be sorted on the second char so they are grouped together, after that sorted by first char.

I tried a bunch of things with .filter and .sort_by but was not successful.

答案1

得分: 3

你可以通过迭代器访问字符串中的字符:

#[test]
fn sort_by_second_char() {
    let mut input = [
        "3r", "2n", "2s", "7r", "1s", "1s", "6r", "1s", "1n", "1n", "5n", "9n", "3r",
    ];
    let output = [
        "1n", "1n", "2n", "5n", "9n", "3r", "3r", "6r", "7r", "1s", "1s", "1s", "2s",
    ];

    // this does not break even if the input string is of invalid format, if
    // you are sure they are valid you can unwrap.
    fn get_second_char(s: &&str) -> (Option<char>, Option<char>) {
        let mut chars = s.chars();
        let [num, char] = [chars.next(), chars.next()];
        (char, num)
    }

    input.sort_by_key(get_second_char);

    assert_eq!(input, output);
}

注意,如果元组的各个元素实现了Ord,则元组本身也会实现OrdOption如果包装的类型实现了Ordchar),那么Option也会实现Ord

英文:

you can access chars in a string trough an iterator:

#[test]
fn sort_by_second_char() {
    let mut input = [
        &quot;3r&quot;, &quot;2n&quot;, &quot;2s&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;6r&quot;, &quot;1s&quot;, &quot;1n&quot;, &quot;1n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;,
    ];
    let output = [
        &quot;1n&quot;, &quot;1n&quot;, &quot;2n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;, &quot;3r&quot;, &quot;6r&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;2s&quot;,
    ];

    // this does not break even if the input string is of invalid format, if
    // you are sure they are valid you can unwrap.
    fn get_second_char(s: &amp;&amp;str) -&gt; (Option&lt;char&gt;, Option&lt;char&gt;) {
        let mut chars = s.chars();
        let [num, char] = [chars.next(), chars.next()];
        (char, num)
    }

    input.sort_by_key(get_second_char);

    assert_eq!(input, output);
}

Note that tuples implement Ord if their respective elements implement Ord Option implements Ord if type it wraps implements Ord (char)

答案2

得分: 2

If your strings are always two characters long, and you always want to sort them by the second character first, you can use .sort_by with a comparator which looks at the strings in reverse:

let mut input = vec!(&quot;3r&quot;, &quot;2n&quot;, &quot;2s&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;6r&quot;, &quot;1s&quot;, &quot;1n&quot;, &quot;1n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;);
input.sort_by(|a, b| a.chars().rev().cmp(b.chars().rev()));
let expected = vec!(&quot;1n&quot;, &quot;1n&quot;, &quot;2n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;, &quot;3r&quot;, &quot;6r&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;2s&quot;);
assert!(input == expected);
英文:

If your strings are always two characters long, and you always want to sort them by the second character first, you can use .sort_by with a comparator which looks at the strings in reverse:

let mut input = vec!(&quot;3r&quot;, &quot;2n&quot;, &quot;2s&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;6r&quot;, &quot;1s&quot;, &quot;1n&quot;, &quot;1n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;);
input.sort_by(|a, b| a.chars().rev().cmp(b.chars().rev()));
let expected = vec!(&quot;1n&quot;, &quot;1n&quot;, &quot;2n&quot;, &quot;5n&quot;, &quot;9n&quot;, &quot;3r&quot;, &quot;3r&quot;, &quot;6r&quot;, &quot;7r&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;1s&quot;, &quot;2s&quot;);
assert!(input == expected);

huangapple
  • 本文由 发表于 2023年5月25日 17:09:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76330609.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定