Wie kann ich beim Sortieren mit mehreren Schlüsseln die Reihenfolge eines einzelnen Schlüssels umkehren? Zum Beispiel:Umgekehrter spezifischer Schlüssel beim Sortieren mit mehreren Schlüsseln
vec.sort_by_key(|k| (foo(k).reverse(), bar(k)));
Wie kann ich beim Sortieren mit mehreren Schlüsseln die Reihenfolge eines einzelnen Schlüssels umkehren? Zum Beispiel:Umgekehrter spezifischer Schlüssel beim Sortieren mit mehreren Schlüsseln
vec.sort_by_key(|k| (foo(k).reverse(), bar(k)));
können Sie sort_by
mit Ordering::reverse
gepaart anstelle von sort_by_key
.
use std::cmp::Ordering;
#[derive(Debug)]
struct Foo(&'static str, u8);
impl Foo {
fn name(&self) -> &str { self.0 }
fn len(&self) -> u8 { self.1 }
}
fn main() {
let mut vec = vec![Foo("alpha", 1), Foo("beta", 2), Foo("beta", 1)];
vec.sort_by(|a, b| {
match a.name().cmp(b.name()).reverse() {
Ordering::Equal => a.len().cmp(&b.len()),
other => other,
}
});
println!("{:?}", vec);
}
Diese Art in umgekehrter alphabetischer Reihenfolge, sind in aufsteigender numerischer Reihenfolge dann Bindungen sortiert:
[Foo("beta", 1), Foo("beta", 2), Foo("alpha", 1)]
Wenn RFC 1677 akzeptiert und umgesetzt wird, dies aussehen könnte:
vec.sort_by(|a, b| {
a.name().cmp(b.name()).reverse()
.then(a.len().cmp(&b.len()))
});
Wenn Sie haben etwas, das natürlich negiert/invertiert werden kann, können Sie simply negate the key.
Danke. So ist 'sort_by' mächtiger als' sort_by_key': 'sort_by' kann alles, was' sort_by_key' kann tun, aber 'sort_by_key' kann nicht alles, was' sort_by' kann. Was ist der Vorteil von 'sort_by_key'? – HiDefender
@HiDefender ist es viel einfacher für extrem häufige Fälle. Es kann sogar für Ihren Fall funktionieren, wie ich in der anderen Frage verlinkt habe. – Shepmaster
Noch einmal, danke. Zwei weitere Fragen: 1. Übergeben Sie '& b.len()' im zweiten Vergleich. Warum unterstützt cmp() nicht die Weitergabe von Eigentumsrechten, nur die Ausleihe? 2. Ist es notwendig, dass Ihre Struktur "[derived (Debug)]" hat? Konnte es ohne das nicht sortiert werden? – HiDefender
Hier ist eine ähnliche Herangehensweise an das Problem: eine Funktion für die Verkettung mehrerer Ordnungen erstellen:
/// chain two orderings: the first one gets more priority
fn chain_ordering(o1: Ordering, o2: Ordering) -> Ordering {
match o1 {
Ordering::Equal => o2,
_ => o1,
}
}
Dann sort_by
verwenden, möglicherweise mit Pattern-Matching, die Reihenfolge der einzelnen Tasten zu erzeugen:
#[derive(Debug, PartialEq)]
struct HeroSkill(&'static str, &'static str);
fn main() {
// a vector of hero names and super powers
let mut v = vec![
HeroSkill("Bob", "X"),
HeroSkill("Bob", "Y"),
HeroSkill("Alice", "X")
];
// sort by name, then by super power, where Y is more powerful than X
v.sort_by(|&HeroSkill(name1, power1), &HeroSkill(name2, power2)| {
chain_ordering(name1.cmp(name2), power1.cmp(power2).reverse())
});
assert_eq!(v, vec![
HeroSkill("Alice", "X"),
HeroSkill("Bob", "Y"),
HeroSkill("Bob", "X")
]);
}
Die revord
Kiste (documentation) bietet eine Struktur, RevOrd
, das einen Wert umschließt und PartialOrd
und Ord
implementiert, indem partial_cmp
und cmp
mit vertauschten Argumenten aufgerufen werden, um die umgekehrte Reihenfolge zurückzugeben. Umbrechen Sie einfach den Schlüssel, um in absteigender Reihenfolge in einer RevOrd
Struktur zu sortieren.
vec.sort_by_key(|k| (RevOrd(foo(k)), bar(k)));
Mit mehreren Schlüsseln meinst du mehrere Sortierkriterien (jede mit absteigender Priorität)? –
@ E_net4 Ja. Wenn das Tupel (x, y) war, dann sortiere mit x und brich die Bindungen mit y. Außer in diesem Fall möchte ich eine absteigende Reihenfolge für x. – HiDefender
Ihr Beispiel funktioniert gut für die entsprechenden Implementierungen von 'foo',' reverse' und 'bar'. – Shepmaster