Roberto Pezzali
Roberto Pezzali

Reputation: 2494

Javascript, dynamically create an empty object copy during a map

I'm struggling to find a good solution to process my array of objects.

I have two arrays:

let structure = ["horizontal","vertical","small","small","small"]

let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
            {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
            {"id":6,"title":"xxxxx","format":"small","position":2}, 
            {"id":9,"title":"xxxxx","format":"small","position":3}, 
            {"id":11,"title":"xxxxx","format":"small","position":4}]

Edit: Items are more complex than this: it has about 15 attributes...

structure has a dynamic length and is my reference array. When I change structure I must remap the items array changing the format according to structure. So if I change structure to

let structure = ["horizontal","vertical","vertical","vertical","small"]

The array must change to

 let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
              {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
              {"id":6,"title":"xxxxx","format":"vertical","position":2}, 
              {"id":9,"title":"xxxxx","format":"vertical","position":3}, 
              {"id":11,"title":"xxxxx","format":"small","position":4}]

This can be done with a map. This is my Vue method, I map the structure and use the function changeStructure I change the format.

methods: {
      changeStructure(object,structure) {
        object.format = structure
        return object
      },
      updateCoverElements() {
        let structure = this.coverTypes[this.currentCoverVersion]
        let elements = this.coverElements
        let changeStructure = this.changeStructure

        let revisedElement = structure.map(function(structure, index) {
          return changeStructure(elements[index],structure)
        });
        console.log(revisedElement);
      }
    },

But the problem is that, as I told before, structure has a dynamic length.

So when I change to

let structure = ["horizontal","vertical","vertical"]

Item results must be

let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
            {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
            {"id":6,"title":"xxxxx","format":"vertical","position":2}]

This is not a problem, if the new structure length has less elements.

But when I change to

let structure = ["horizontal","vertical","vertical","vertical","vertical","vertical","vertical"]

Item results must be

let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
             {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
             {"id":6,"title":"xxxxx","format":"vertical","position":2},
             {"id":"","title":"","format":"vertical","position":3}, 
             {"id":"","title":"","format":"vertical","position":4},
             {"id":"","title":"","format":"vertical","position":5}, 
             {"id":"","title":"","format":"vertical","position":6}]

And here is the problem: I cannot find a good way to dynamically create an object with the same identical structure as other items objects (a copy), with every field empty except for position, the index of the array, and format.

Upvotes: 0

Views: 1516

Answers (3)

adiga
adiga

Reputation: 35222

You could use the spread syntax like this. If items has a value at the index, it will overwrite the default id and title values.

let structure = ["horizontal","vertical","vertical","vertical","vertical","vertical","vertical"]

let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
            {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
            {"id":6,"title":"xxxxx","format":"vertical","position":2}]

const defaultObj = { id: '', title: '' }

const newItems = structure.map((format, position) => {
  return { ...defaultObj, ...items[position], format, position }
})

console.log(newItems)

Upvotes: 2

duhaime
duhaime

Reputation: 27594

Just slice off a new copy of items with max structure.length items, then iterate through your new clone of items and set each format attribute. Finally, create new objects for any elements in structure that don't have a corresponding partner in items:

var structure = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

var items = [
  {'id':1,'title':'xxxxx','format':'horizontal','position':0}, 
  {'id':3,'title':'xxxxx','format':'vertical',  'position':1}, 
  {'id':6,'title':'xxxxx','format':'vertical',  'position':2},
];

// update all extant items
var _items = Object.assign([], items.slice(0, structure.length));
_items.forEach(function(i, idx) { i.format = structure[idx] });

// create any new items
for (var i=_items.length; i<structure.length; i++) {
  _items.push(Object.assign({}, items[0], {
    id: '',
    title: '',
    position: i,
    format: structure[i],
  }))
}

console.log(_items)

Upvotes: 1

hygull
hygull

Reputation: 8740

The best way to solve this problem using map() method would be to organize your implementation functional so that you could call it many times with a different set of data wherever you need (the concept of reusability).

Here is what I have tried. I have defined the function named getAlteredArray(items, structure) which returns the desired array. Note that if you are looking to use map() method means you want a new array (I mean you don't want to alter the passed array).

I have pasted the o/p on the code itself (it is commented out).

// function that creates new array with desired items and returns to the caller
function getAlteredArray(items, structure) {
    let newArr = items.map((obj, index) => {
        // obj => {"id":1,"title":"xxxxx","format":"horizontal","position":0}
        obj["format"] = structure[index]
        return obj
    })

    return newArr
}

// function that creates set of data needs to be passed to getAlteredArray() function
function test() {
    let items = [{"id":1,"title":"xxxxx","format":"horizontal","position":0}, 
            {"id":3,"title":"xxxxx","format":"vertical","position":1}, 
            {"id":6,"title":"xxxxx","format":"small","position":2}, 
            {"id":9,"title":"xxxxx","format":"small","position":3}, 
            {"id":11,"title":"xxxxx","format":"small","position":4}]

    // TEST 1 - Call getAlteredArray() with `items` & `structure`
    let structure = ["horizontal","vertical","vertical","vertical","small"]
    let newArr = getAlteredArray(items, structure)
    console.log(newArr)
    /*
        [ { id: 1, title: 'xxxxx', format: 'horizontal', position: 0 },
          { id: 3, title: 'xxxxx', format: 'vertical', position: 1 },
          { id: 6, title: 'xxxxx', format: 'vertical', position: 2 },
          { id: 9, title: 'xxxxx', format: 'vertical', position: 3 },
          { id: 11, title: 'xxxxx', format: 'small', position: 4 } ]
    */

    // TEST 2 
    let structure2 = ["horizontal","vertical","small","small","small"]
    let newArr2 = getAlteredArray(items, structure2)
    console.log(newArr2)
    /*
        [ { id: 1, title: 'xxxxx', format: 'horizontal', position: 0 },
          { id: 3, title: 'xxxxx', format: 'vertical', position: 1 },
          { id: 6, title: 'xxxxx', format: 'small', position: 2 },
          { id: 9, title: 'xxxxx', format: 'small', position: 3 },
          { id: 11, title: 'xxxxx', format: 'small', position: 4 } ]    
    */
}

// Start
test()

Upvotes: 0

Related Questions