8000 Support for replacement in array · Issue #1967 · lodash/lodash · GitHub
[go: up one dir, main page]

Skip to content

Support for replacement in array #1967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8000 Closed
jfmengels opened this issue Feb 9, 2016 · 8 comments
Closed

Support for replacement in array #1967

jfmengels opened this issue Feb 9, 2016 · 8 comments

Comments

@jfmengels
Copy link
Contributor

I am often (in multiple projects) reimplementing the same utility function, that replaces a value in an array based on some condition (a position or a field is equal to X), without mutating the original array (like map in that regard):

array.map(function(value) {
  if (value.id !== ID) {
    return value;
  }
  return REPLACEMENT;
});

array.map(function(value, index) {
  if (index !== POSITION) {
    return value;
  }
  return REPLACEMENT;
});

I would like to dip my toe in the water and see if others would be interested in having a function that does this.

/**
 * Replace a value in `array` when `condition` matches.
 * 
 * @param {Array} array The collection to iterate over.
 * @param {Function|number|Object} condition Condition to match.
 * @param {*} iteratee The function invoked if `condition` matches, or the replacement value.
 * @return {Array} Returns the new mapped array.
 */
function mapReplace(array, condition, iteratee) {
  // ...
}

// Mapped in lodash/fp ([2, 0, 1])
_.mapReplace(condition, iteratee, array);

Example

function plusTen(x) {
  return x + 10;
}

function isEven(x) {
  return x % 2 === 0;
}

var array = [0, 1, 2, 3];

// Using index as condition and simple value as iteratee ( = replacement)
_.mapReplace(array, 2, 'replacement');
// => [0, 1, 'replacement', 3]

// Using index as condition and function as iteratee
_.mapReplace(array, 2, plusTen);
// => [0, 1, 12, 3]

// Using function as condition and function as iteratee
_.mapReplace(array, isEven, plusTen);
// => [10, 1, 12, 3]
// or if it is only applied to the first found element, and a mapReplaceAll exists:
// => [10, 1, 2, 3]

// Using object to get field as condition and value as iteratee
_.mapReplace([{id: 0, val: 0}, {id: 1, val: 1}], {id: 1}, {id: 1, foo: 'bar'});
// => [{id: 0, val: 0}, {id: 1, foo: 'bar'}]

I would have liked it to be named replace, but since that is already taken... ^^'
I used mapReplace in the example but open to suggestions.

I'd argue it would be nice to have one function to update the first found item, and one to update them all (kind of like the proposal for replaceAll).

@jdalton
Copy link
Member
jdalton commented Feb 9, 2016

Thanks @jfmengels!

We'll keep an eye on the popularity of the request.

Side note:
I'd make the signature (array, condition, iteratee) to align closer to _.replace.

@jdalton jdalton closed this as completed Feb 9, 2016
@jfmengels
Copy link
Contributor Author

Agreed on the signature (updated it), it's what I was using in the examples actually.

@slorber
Copy link
slorber commented Feb 25, 2016

+1 for this feature

I'd also find it useful to have the possibility to add multiple elements at a given array index (immutable splice)

@Gaafar
Copy link
Gaafar commented Jul 4, 2016

This would be really useful in reactjs to update an array in the state. +1

@EthanLin-TWer
Copy link

+1 for this feature. In our cases we need to maintain an array(or could be an object) of the app's tabs status in Redux like this:

const initialState = Immutable.from({
  selected: [ 
    { page: Pages.NEWS, active: true, tabs: [
      { tab: Tabs.HOTTEST, active: false, subTabs: []}, 
      { tab: Tabs.HISTORY, active: true, subTabs: []},
      { tab: Tabs.RECOMMENDATIONS, active: false, subTabs: []},
    ]},
    { page: Pages.VIDEOS, active: false, tabs: []},
  ],
})

While an updateActiveTab(Pages.NEWS, Tabs.HOTTEST) action is dispatched, we'd like to update the 'hottest' tab under the news page as active: true and others(history news and recommendations) as active: false. In this case the proposed mapReplace function will definitely help.

Using other data structure might help in our case but I'm just posting the possible situation we've been met where mapReplace would make life easier.

@gablabelle
Copy link
gablabelle commented Oct 19, 2019

Hello guys, so I was curious... Is it currently possible to do something like this in lodash? Or we still have to use our own util function across projects (basic example):

const updateArray = (list, updatedItem) => {
   const index = list.findIndex(item => item.id === updatedItem.id);
   return [
    ...list.slice(0, index),
    ...updatedItem,
    ...list.slice(index + 1)
   ];
}

Because what's the process? Suggestions are made, tags like enhancement and votes needed are added to the issue and then the issue gets closed, then what?

@StarScape
Copy link

Bump. I find myself needing this a lot and would very much like to see this feature.

@riotrah
Copy link
riotrah commented Mar 24, 2022

Hi, please forgive if "bump+1" comments on issues is the wrong kind of vote (per your docs), and do not want to appear entitled, but am not sure anyways given the radio silence - so I'm adding both. Apologies if my doing so on several diff issues constitutes spam ( I genuinely am not sure and not intending it to be! )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

8 participants
0