Search code examples
javascriptjavascript-objectsgenerator

Javascript object generator


Is there a generator approach to constructing a mapping (object)? I just need key/value mapping.

For generating array, I can write something like this

function* rangeA(start, stop) {
  while(start < stop)
    yield start++
}

let data = [...rangeA(1, 3), ...rangeA(20, 22)]
// data is [1, 2, 20, 21]

Non generator approach to construct an object in a similar way can look like this

function rangeB(start, stop) {
  let result = {}
  while(start < stop) {
    result[start] = start
    start++
  }
  return result
}
let data = {...rangeB(1, 3), ...rangeB(20, 22)}
// data is {1: 1, 2: 2, 20: 20, 21: 21}

Is there a generator approach to construct an object? Something like this

// DOES NOT WORK
function* rangeC(start, stop) {
  while(start < stop) {
    yield {[start]: start}
    start++
  }
}
let data = {...rangeC(1, 3), ...rangeC(20, 22)}
// data is unfortunately an empty object

let data2 = [...rangeC(1, 3), ...rangeC(20, 22)]
// data2 is obviously [{1: 1}, {2: 2}, {3: 3}, {20: 20}, {21: 21}]
// which is not what I want.

let data3 = data2.reduce((a, b) => ({...a, ...b}))
// data3 is finally {1: 1, 2: 2, 20: 20, 21: 21}
// but it seems overcomplicated to me

Solution

  • Try using Object.fromEntries:

    function* rangeC(start, stop) {
      while(start < stop) {
        // Replace the curly brackets with square ones here
        yield [start, start]
        start++
      }
    }
    let data = Object.fromEntries([...rangeC(1, 3), ...rangeC(20, 22)])
    

    For one generator, you can pass it directly:

    let data = Object.fromEntries(range(1,3))
    

    Or create a chain method to process multiple:

    function* chain(...generators) {
        for (let generator of generators) {
            yield* generator;
        }
    }
    
    let data = Object.fromEntries(chain(rangeC(1,3), rangeC(10,15)))