use indexmap::IndexMap;
use std::collections::HashMap;
use std::hash::Hash;
pub trait InsertOrAddToMap<K, V> {
fn insert_or_add_to_value(&mut self, key: K, value: V);
}
pub trait ExpandToListMap<L> {
fn to_list_map(&self) -> L;
}
impl<K, V> InsertOrAddToMap<K, V> for HashMap<K, Vec<V>>
where
K: Eq + Hash,
{
fn insert_or_add_to_value(&mut self, key: K, value: V) {
match self.get_mut(&key) {
None => {
self.insert(key, vec![value]);
}
Some(v) => {
v.push(value);
}
}
}
}
impl<K, V> InsertOrAddToMap<K, V> for IndexMap<K, Vec<V>>
where
K: Eq + Hash,
{
fn insert_or_add_to_value(&mut self, key: K, value: V) {
match self.get_mut(&key) {
None => {
self.insert(key, vec![value]);
}
Some(v) => {
v.push(value);
}
}
}
}
impl<K, KR, V, VR> ExpandToListMap<Vec<IndexMap<KR, VR>>> for IndexMap<K, Vec<V>>
where
K: Eq + Hash + ToOwned<Owned = KR>,
KR: Eq + Hash,
V: ToOwned<Owned = VR>,
{
fn to_list_map(&self) -> Vec<IndexMap<KR, VR>> {
let mut capacity = 0;
for v in self.values() {
let len = v.len();
if capacity == 0 && len > 0 {
capacity = 1;
}
capacity *= len;
}
let mut list = Vec::with_capacity(capacity);
list.resize_with(capacity, || IndexMap::new());
for (key, value) in self.iter() {
let mut idx = 0;
while idx < list.len() {
for value in value.iter() {
if let Some(map) = list.get_mut(idx) {
map.insert(key.to_owned(), value.to_owned());
}
idx += 1;
}
}
}
list
}
}
#[allow(unused)]
mod test {
use crate::tina::data::map::{ExpandToListMap, InsertOrAddToMap};
use indexmap::IndexMap;
use std::collections::HashMap;
#[test]
fn test_expand_to_list() {
let mut map: IndexMap<i32, Vec<i32>> = IndexMap::new();
map.insert_or_add_to_value(1, 1);
map.insert_or_add_to_value(1, 2);
map.insert_or_add_to_value(2, 1);
map.insert_or_add_to_value(2, 2);
map.insert_or_add_to_value(2, 3);
let expand = map.to_list_map();
let mut check: Vec<IndexMap<i32, i32>> = Vec::new();
{
let mut map = IndexMap::new();
map.insert(1, 1);
map.insert(2, 1);
check.push(map);
}
{
let mut map = IndexMap::new();
map.insert(1, 2);
map.insert(2, 2);
check.push(map);
}
{
let mut map = IndexMap::new();
map.insert(1, 1);
map.insert(2, 3);
check.push(map);
}
{
let mut map = IndexMap::new();
map.insert(1, 2);
map.insert(2, 1);
check.push(map);
}
{
let mut map = IndexMap::new();
map.insert(1, 1);
map.insert(2, 2);
check.push(map);
}
{
let mut map = IndexMap::new();
map.insert(1, 2);
map.insert(2, 3);
check.push(map);
}
assert_eq!(expand, check);
}
}