Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Into<std::collections::HashMap> #345

Open
SamuelMarks opened this issue Sep 7, 2024 · 1 comment
Open

Feature request: Into<std::collections::HashMap> #345

SamuelMarks opened this issue Sep 7, 2024 · 1 comment

Comments

@SamuelMarks
Copy link

SamuelMarks commented Sep 7, 2024

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.

@cuviper
Copy link
Member

cuviper commented Sep 7, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants