javascripttypescriptlodash

How to manipulate some properties and sub properties with lodash


I have some object datas that i want to multiply by a number, the problem is i want all properties or sub properties that matches some names to by multiplied by that number without knowing the actual type of the data

here is an example:

// original api response data
let data = {
    id: 4,
    price: 100,
    discount: 10,
    total_price: 90,
    create_date: '2024-09-06T14:35:42.759Z',
    parent_id: 3,
    parent: {
        id: 3,
        price: 1000,
        discount: 0,
        total_price: 1000,
        create_date: '2024-09-06T13:35:42.759Z',
    },
    items: [
        {
            id: 10,
            name: 'item 1',
            cost: 3,
            price: 5,
            quantity: 5
        },
    ],
    others: {
        otherValues: [
            {
                id: 9,
                name: 'other 1',
                price: 10,
                quantity: 1
            },
        ]
    }
}

// calculate function
const calculate = (data, multipler, keys) => {
    // the lodash magic
    ...
}

// calculating the data
let calculated = calculate(data, 1.5, ['price', 'total_price', 'cost'])
/*
expected result: 
let data = {
    id: 4,
    price: 150,
    discount: 10,
    total_price: 135,
    create_date: '2024-09-06T14:35:42.759Z',
    parent_id: 3,
    parent: {
        id: 3,
        price: 1500,
        discount: 0,
        total_price: 1500,
        create_date: '2024-09-06T13:35:42.759Z',
    },
    items: [
        {
            id: 10,
            name: 'item 1',
            cost: 4.5,
            price: 7.5,
            quantity: 5
        },
    ],
    others: {
        otherValues: [
            {
                id: 9,
                name: 'other 1',
                price: 15,
                quantity: 1
            },
        ]
    }
}
*/

in the example only properties and sub properties that are named 'price', 'total_price', and 'cost' have been multiplied, and the object i provided is one of many that are being sent back that the shapes are different and trying to do the manipulation for each is not a great idea

i tried using lodash map mainly but i could not get it to work


Solution

  • A classic iterator. It's a recursion that recurses into values that are objects, doing its thing. It replaces values inplace, but might as well duplicate the original if you want to keep the original tree.

    // calculate function
    const calculate = (obj, multiplier, keys) => {
      if (!obj) {
        return obj
      }
      Object.keys(obj).forEach(key => {
        if (keys.indexOf(key) >= 0) {
          obj[key] *= multiplier
        }
        if (typeof obj[key] === "object") {
          obj[key] = calculate(obj[key], multiplier, keys)
        }
      })
      return obj;
    }
    
    
    
    // original api response data
    let data = {
      id: 4,
      price: 100,
      discount: 10,
      total_price: 90,
      create_date: '2024-09-06T14:35:42.759Z',
      parent_id: 3,
      parent: {
        id: 3,
        price: 1000,
        discount: 0,
        total_price: 1000,
        create_date: '2024-09-06T13:35:42.759Z',
      },
      items: [{
        id: 10,
        name: 'item 1',
        cost: 3,
        price: 5,
        quantity: 5
      }, ],
      others: {
        otherValues: [{
          id: 9,
          name: 'other 1',
          price: 10,
          quantity: 1
        }, ]
      }
    }
    
    
    // calculating the data
    let calculated = calculate(data, 1.5, ['price', 'total_price', 'cost'])
    
    console.log(calculated)
    .as-console-wrapper {
      min-height: 100%;
    }