Consider map-zip function
KittyGiraudel opened this issue · comments
What about a function that makes it possible to zip a list of keys and a list of values to create a map? Kind of like zip
function, but to make a Sass map.
/// An equivalent of `zip` function but for maps.
/// Takes two lists, the first for keys, second for values.
/// @param {List} $keys - Keys for map
/// @param {List} $values - Values for map
/// @return {Map} Freshly created map
/// @see http://sass-lang.com/documentation/Sass/Script/Functions.html#zip-instance_method
@function map-zip($keys, $values) {
$l-keys: length($keys);
$l-values: length($values);
$min: min($l-keys, $l-values);
$map: ();
@if $l-keys != $l-values {
@warn "There are #{$l-keys} key(s) for #{$l-values} value(s) in the map for `map-zip`. "
+ "Resulting map will only have #{$min} pairs.";
}
@if $min == 0 {
@return $map;
}
@for $i from 1 through $min {
$map: map-merge($map, (nth($keys, $i): nth($values, $i)));
}
@return $map;
}
Test:
test {
$keys: a b c;
$values: 1, 2, 3, 4;
map-zip: inspect( map-zip( $keys, $values ) );
$keys: ();
$values: a b c;
map-zip: inspect( map-zip( $keys, $values ) );
}
Result:
test {
map-zip: (a: 1, b: 2, c: 3);
map-zip: ();
}
Idea of application: make sure all keys from a map are unquoted. For convenience, let's say you have this little walk
function:
@function walk($list, $function, $args...) {
@if not function-exists($function) {
@error "There is no `#{$function}` function.";
}
@for $i from 1 through length($list) {
$list: set-nth($list, $i, call($function, nth($list, $i), $args...));
}
@return $list;
}
The idea is to apply the unquote function to all keys of the map then zip back the updated keys with the values. Easy peasy. It's a one-liner:
$map: ("a": 1, 'b': 2, c: 3);
$new-map: map-zip( walk( map-keys( $map ), "unquote" ), map-values( $map ) );
application {
initial-map: inspect($map);
new-map: inspect($new-map);
}
Result:
application {
initial-map: ("a": 1, "b": 2, c: 3);
new-map: (a: 1, b: 2, c: 3);
}