indexmap icon indicating copy to clipboard operation
indexmap copied to clipboard

Feature request: `Into<std::collections::HashMap>`

Open SamuelMarks opened this issue 1 year ago • 1 comments

Many third party crates require the OG.

Sure I can do this:

let mut hm = std::collections::HashMap::<String, String>::with_capacity(env.len());
for (k,v) in env.iter() {
    hm.insert(k.to_owned(), v.to_owned());
}

But it's not as ergonomic as an Into or From.

SamuelMarks avatar Sep 07 '24 06:09 SamuelMarks

For Copy-able key-values (less general than ToOwned), you could change your example to:

let mut hm = std::collections::HashMap::<String, String>::with_capacity(env.len());
hm.extend(env.iter()); // using `Extend<(&K, &V)>`

(edit: I wrote Clone-able at first, but that Extend requires Copy. So this doesn't apply to your String key-values.)

I would expect Into to pass ownership though, in which case you can simply write HashMap::from_iter(env). When using the conversion in an inferrable context, you can write foo(env.into_iter().collect()). Either way, this involves a bit of complexity in rehashing everything, so I don't think it should be hidden behind Into.

However, if raw_entry_mut ever stabilizes, we could possibly do better for conversions that keep the same underlying hasher, because IndexMap also caches the hash values in its internal Bucket. Something like:

impl<K, V, S> From<IndexMap<K, V, S>> for HashMap<K, V, S>
where
    K: Eq + Hash,
    S: BuildHasher,
{
    fn from(imap: IndexMap<K, V, S>) -> Self {
        let mut hmap = HashMap::with_capacity_and_hasher(imap.len(), imap.hash_builder);
        for bucket in imap.core.into_entries() {
            hmap
                .raw_entry_mut()
                .from_key_hashed_nocheck(bucket.hash.get(), &bucket.key)
                .or_insert(bucket.key, bucket.value);
        }
        hmap
    }
}

In theory, IndexSet to HashSet could do the same, but there's no such raw API at all yet.

cuviper avatar Sep 07 '24 18:09 cuviper

Given the FCP-close on rust-lang/rust#56167, I don't think any advanced raw-entry translation will be possible, and for the rest there's FromIterator.

cuviper avatar Feb 26 '25 23:02 cuviper