How can we modify specific values of an object using Lodash and return the updated object?

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

My aim is to adjust the values of certain fruits while being able to reference their current values.

For example:

const premiumFrutis = _.doSomething(fruits, apple + 2, banana + 3)

// premiumFrutis = {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 8
// }

Answer №1

One way to achieve this is by using _.assignWith or _.assignInWith. The notable distinction lies in the fact that while assignIn traverses the prototype chain, with plain objects, both functions yield the same result.

In either scenario, a customizer function can be supplied to determine how object values are merged. For example:

const combineValues = (srcValue, objValue) => 
      srcValue + objValue;

This simple implementation sums up values for corresponding keys:

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

const combineValues = (srcValue, objValue) => 
  srcValue + objValue;

const modification = {apple: 2, banana: 3};

const premiumFrutis = _.assignWith(fruits, modification, combineValues);
console.log(premiumFrutis);
// {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 8
// }
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="84e8ebe0e5f7ecc4b0aab5b3aab6b5">[email protected]</a>/lodash.min.js"></script>

Nevertheless, implementing such a custom function may not even be necessary since Lodash already offers _.add, ready to be employed directly:

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

const modification = {apple: 2, banana: 3};

const premiumFrutis = _.assignWith(fruits, modification, _.add);
console.log(premiumFrutis);
// {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 8
// }
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ff93909b9e8c97bfcbd1cec8d1cdce">[email protected]</a>/lodash.min.js"></script>

The capability extends to subtraction if negative values are provided:

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

const modification = {apple: 2, banana: -1};

const premiumFrutis = _.assignWith(fruits, modification, _.add);
console.log(premiumFrutis);
// {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 4
// }
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="600c0f0401130820544e51574e5251">[email protected]</a>/lodash.min.js"></script>


An issue may arise when more modifications are provided than there are keys in the original objects:

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

const modification = {apple: 2, banana: 3, lemon: 42};

const premiumFrutis = _.assignWith(fruits, modification, _.add);
console.log(premiumFrutis);
// {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 8,
//     lemon: 42
// }
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="55393a3134263d15617b64627b6764">[email protected]</a>/lodash.min.js"></script>

If no new items need to be added, _.pickBy could be utilized to eliminate any modifications not present in the initial object:

const fruits = {
    apple: 2,
    orange: 3,
    grape: 4,
    banana: 5
}

const modification = {apple: 2, banana: 3, lemon: 42};
const onlyExisting = _.pickBy(modification, (value, key) => key in fruits);

const premiumFrutis = _.assignWith(fruits, onlyExisting, _.add);
console.log(premiumFrutis);
// {
//     apple: 4,
//     orange: 3,
//     grape: 4,
//     banana: 8
// }
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a2cecdc6c3d1cae2968c93958c9093">[email protected]</a>/lodash.min.js"></script>

Answer №2

To achieve this, you can develop a mixin function. Start by duplicating the original object and then apply the changes from the update object on top of it.

_.mixin({
  /**
   * Assign incremental values to a source object for a given update object.
   * @param {object} source
   * @param {object} update
   * @return {object} updated (cloned) source object
   */
  doSomething: function(source, update) {
    return _.reduce(update, function(result, value, key) {
      return _.assign(result, { [key]: source[key] + value });
    }, _.clone(source));
  }
});

const fruits = {
  apple: 2,
  orange: 3,
  grape: 4,
  banana: 5
};

const premiumFruits = _.doSomething(fruits, {
  apple:  2, // increment apple by 2
  banana: 3  // increment banana by 3
});

console.log(premiumFruits);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Output

  "apple": 4,
  "orange": 3,
  "grape": 4,
  "banana": 8
}

ES6 Version without Lodash

const doSomething = (source, update) =>
  Object
    .entries(update)
    .reduce((result, [key, value]) =>
      ({ ...result, [key]: source[key] + value }),
      { ...source })

const fruits = {
  apple: 2,
  orange: 3,
  grape: 4,
  banana: 5,
}

const premiumFruits = doSomething(fruits, {
  apple:  2, // increment apple by 2
  banana: 3, // increment banana by 3
})

console.log(premiumFruits)


Update

Here is VLAZ's final example, but as a Lodash mixin:

Note: I replaced the key in fruits call with _.has(fruits, key) to make it more portable.

_.mixin({
  doSomething: function(source, update) {
    return _.assignWith(
      source,
      _.pickBy(update, (v, k) => _.has(source, k)),
      _.add
    );
  } 
});

const fruits = {
  apple: 2,
  orange: 3,
  grape: 4,
  banana: 5
};

const premiumFruits = _.doSomething(fruits, {
  apple:  2, // Increment apple by 2
  banana: 3, // Increment banana by 3
  lemon: 42  // Do nothing, does not exist!
});

console.log(premiumFruits);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to dynamically update the polyline on the map when I drag a marker to change the path, removing the previous one in the process?

I'm still fairly new to working with Javascript and the Google Maps API. I've come across various solutions to a similar issue that I'm facing, but none of them seem to work for my specific code. I'm starting to question whether the pol ...

Partially extended texture in Three.js

Currently, I am using the Collada loader in Three.js r65 to load my 3D object. Upon loading, I apply a texture to all parts of the model using the following code snippet. var loader = new THREE.ColladaLoader(); loader.options.convertUpAxis = true; loader ...

Eradicating Pinpointers on Navigation Tool (Google Maps)

I have a feature that utilizes an ajax request to generate a marker or multiple markers when the user interacts with the map. Once a marker is created at a specific location by the user, I then set up a click event on the marker itself. The issue arises w ...

Routing static pages in Angular 2

I successfully created a static page using Angular 2. When I run ng serve and visit my page, it functions as intended. Specifically, I can navigate to a specific page by typing in the URL, such as www.mysite.com/resume. However, after uploading it to my si ...

The ReactJS component is unable to resolve the specified domain name

Whenever I utilize a component like const React = require('react'); const dns = require('dns'); class DnsResolver extends React.Component { componentDidMount() { dns.resolve('https://www.google.com', (err, addres ...

Extracting a floating picture from an Excel spreadsheet using ReactJS

Is it possible to extract an image from an Excel sheet that is not contained within a cell, but instead appears to be floating above the cells? The XLSX library only gathers cell information and does not provide a solution. Are there alternative methods su ...

Adjusting SVG size based on the position of the cursor for transforming origin

My goal is to scale an SVG circle using the trackpad (by moving two fingers up and down), with the origin of the transform being the cursor position. Initially, the scaling works as intended, but on subsequent attempts, the circle changes position, which s ...

When using AutoComplete in MUI, I encountered an issue while attempting to assign a default value to the checkbox from an API. Instead of achieving the desired result, I received an error stating "(inter

Within this snippet, I am seeking to retrieve a default value from the API to populate a checkbox initially. I have employed the Material-UI Autocomplete component, which includes a defaultValue prop. Despite my efforts to utilize this prop, I am encounter ...

Exploring Mixed Type Arrays Initialization in Typescript using Class-Transformer Library

In my class, I have a property member that is of type array. Each item in the array can be of various types such as MetaViewDatalinked or MetaViewContainer, as shown below class MetaViewContainer{ children: (MetaViewDatalinked | MetaViewContainer)[]; ...

What is the best way to eliminate HTML <li> bullets using codebehind?

When working in codebehind, I often create an HTML list using the following method: HtmlGenericControl list = new HtmlGenericControl("ul"); for (int i = 0; i < 10; i++) { HtmlGenericControl listItem = new HtmlGenericControl("li"); Label textLabel ...

Exploring different pages in an Ionic and AngularJS mobile application

I am brand new to the world of Ionic and AngularJS. I have just started working on a simple project but have hit a roadblock. My goal is, To create a login page and a register page. When a user clicks the register button on the login page, they should be ...

JavaScript: The power of nested array manipulation

I'm having trouble extracting data from a parsed JSON array obtained from a shipping company. Specifically, I am attempting to retrieve the short_name of Cleveland, OH, but all my attempts to access this information have been unsuccessful. When I use: ...

Is there a way for me to retrieve the name and extension of an attached file in an input field of type "text"?

Could you assist me with a task? I have a table and I would like to extract the name and extension of each file and insert it into an input field below each "file" type input. This information will then be saved into a MySQL database, allowing me to create ...

Ways to allocate space evenly between components of the same size in React Native

As a beginner in Javascript and React-native, I have been experimenting with the technology to assess its viability for potential use in my current workplace. However, I have encountered some challenges with the user interface. To enhance my understanding ...

Is there a way to append the current path to a link that leads to another URL?

I am currently in the process of separating a website, with the English version being on the subdomain en. and the French version residing on the www. Before making this change, I have a drop-down menu that allows users to select their preferred language ...

Struggling to pass Chai tests with Node and Express.js when trying to handle POST requests

Working through a Chai testing exercise and struggling to pass the POST route tests. Encountering two specific errors: 1) Todo API: POST /v1/todos Issue with creating and returning new todo using valid data: Header 'location' should ...

Is today within the current week? Utilizing Moment JS for time tracking

There is a problem that I am facing. Can you assist me in determining whether the day falls within the current week? I am currently developing a weather forecast service and need to validate if a given day is within the current week. The only clue I have ...

Guide to adding sound effects to your Vue 3 app using the Composition API

I'm having trouble setting up a basic button click feature in Vue 3 Composition API to play a sound effect. In my setup function, I have imported an mp3 sound effect from the assets folder and passed it into a ref method with an HTMLAudioElement type, ...

Is there a similar effect in jQuery? This is achieved using prototype

Simply click on the comments link. Observe how the comments smoothly appear, as if sliding down. Also, try clicking on 'hide' and see what happens. ...

Determine the character's position in an input field by tracking mouse movements

I am in need of a way to determine the position of a character in an input field based on mouse movement. For example, if the input field contains the value 'abcde' and I hover my mouse over the character 'a', the position should be ...