rust


How to reverse map of objects to vector of tuples by using an iterator?


What is the easiest way to convert HashMap<String, String> to Vec<(String, Vec<String>)> by using an iterator ? I want to reverse the map.
I've tried to use iter() methods but have no idea how to do a correct map closure implementation for collecting values after:
fn get_aliases(&self) -> Vec<(String, Vec<String>)> {
let mut aliases: HashMap<String, String> = HashMap::new();
aliases.insert("a".to_owned(), "test".to_owned());
aliases.insert("b".to_owned(), "test".to_owned());
aliases.insert("c".to_owned(), "test2".to_owned());
aliases.iter().map(|(ref a, ref c)| {
// what to do here?
}).collect()
// the expected return value is:
// [("test", ["a", "b"]), ("test2", ["c"])]
}
This function will return a vector which says what String keys belong to some object.
I could write a lot of code with for and finds but it seems to me this would be less efficient and I think there is a way to do that by using iterators only.
I could write a lot of code with for and finds but it seems to me this would be less efficient and I think there is a way to do that by using iterators only.
I wouldn't call it a lot of code, and remember that for loops operate on iterators. I've not done any benchmarking, but this is far simpler and I'd expect it to be more performant:
use std::collections::HashMap;
fn get_aliases(aliases: HashMap<String, String>) -> Vec<(String, Vec<String>)> {
let mut x = HashMap::new();
for (k, v) in aliases {
x.entry(v).or_insert_with(Vec::new).push(k)
}
x.into_iter().collect()
}
fn main() {
let mut aliases = HashMap::new();
aliases.insert("a".to_owned(), "test".to_owned());
aliases.insert("b".to_owned(), "test".to_owned());
aliases.insert("c".to_owned(), "test2".to_owned());
println!("{:?}", get_aliases(aliases));
}
It's not trivial, certainly not as trivial as it would be with some other stream libraries that provide the necessary functions.
You can use the itertools crate's group_by to group elements by some key. However, it only groups adjacent elements, so you have to sort them first. Here's my result:
impl A {
pub fn get_aliases(&self) -> Vec<(String, Vec<String>)> {
// Get a Vec of string references for sorting. Reverse element
// order for clarity.
let mut v = self.aliases.iter()
.map(|(a, c)| (&c[..], &a[..])).collect::<Vec<_>>();
v.sort_by_key(|t| t.0); // Make identical keys adjacent.
let g = v.into_iter().group_by(|t| t.0); // Create grouping.
g.into_iter()
.map(|(key, group)| // key is the str with the key
// group is a subiterator that just visits
// elements with that key, Item=&(&str,&str)
(key.to_string(), // result is a tuple of the key as String
group.map(|t| t.1.to_string()).collect())
// and the subiterator turned into a Vec<String>
)
.collect() // finally, turn Iterator<Item=(String, Vec<String>) into Vec
}
}
Going back to your original problem, you have the additional issue that Arc<Object> is only PartialEq (needed by group_by) if Object is; same for Ord (needed by sort_by_key). If your Object type cannot be compared that way and you want to use the pointer identity, your intermediate vector will need to store some newtype wrapper around Arc that uses pointer values for comparison.

Related Links

Can I use a mutable reference method like a value-passing one?
How to execute Rust code directly on Unix systems? (using the shebang)
Convenient 'Option<Box<Any>>' access when success is assured?
Use a closure inside a thread
How to change the variable from inside Fn closure in Rust?
Create mutual reference for rust [duplicate]
How do I safely use an object while it is mutably borrowed?
Workspace giving two different behaviors in Rust
Restricting object lifetimes in Rust
Project with serde cannot compile
Cannot infer an appropriate lifetime for autoref due to conflicting requirements
How to define a hashmap with contents in 1 line in Rust? [duplicate]
How solve “cannot index a value of type `usize`” error?
Preserve lifetime of an argument in another object [duplicate]
How can I use multiple items in a Vec at a time in Rust?
Mutable reference to a tuple as input parameter

Categories

HOME
rust
apache-nifi
tomcat
blast
couchdb
redmine
dafny
apk
lvm
swift2
apache-kafka-connect
ipv6
angular2-template
sympy
responsive-design
elastic-load-balancer
hystrix
ex
dhcp
mahout-recommender
bazaar
infrared
adobe-illustrator
libgit2
data-type-conversion
android-permissions
gollum-wiki
intel
sipp
mod-wsgi
python-appium
unrar
xdebug
android-cardview
npoi
spring-annotations
tsung
sql-execution-plan
cloudera-manager
jfxtras
cups
redgate
jade4j
ng-repeat
assemblies
right-click
pyttsx
word-cloud
elasticsearch-aggregation
jshint
jenkins-slave
music21
xcglogger
nothing
ol3-google-maps
scala-breeze
gestures
sequence-diagram
nivo-slider
stateless-session-bean
emacs25
google-shopping-api
allegro
dmarc
svnserve
gcloud-node
mathml
dojo-build
wicked-pdf
node-glob
sharepoint-apps
mathnet
verisign
jsr363
android-expansion-files
m4
variable-length-array
arbre
self
replicaset
console.log
tidyr
kognitio-wx2
sql-processor
configurable-product
full-text-indexing
otl
webautomation
rails-api
xmi
autonumber
saga
axacropdf
spiral
reentrancy
spark-view-engine
nsfont
memory-pool
fbml
mmc3
drawimage
canonicalization
css-friendly
libxslt
turbine
aptitude
ixmldomdocument
aspbutton
resharper-5.0

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App