at-import / Sassy-Maps

Map helper functions for Sass 3.3 and up

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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);
}