I have two arrays in my react component as follows ...
const [Selected, setSelected] = React.useState([]);
const [NonSelected, setNonSelected] = React.useState([]);
const Tmp_Selected = [
{ "Metric": "AAA", "Weight": 10, "Value": "xxx" },
{ "Metric": "BBB", "Weight": 20, "Value": "xx1" },
{ "Metric": "CCC", "Weight": 30, "Value": "xx2" },
];
const Tmp_NonSelected = [
{ "Metric": "DDD", "Weight": 5, "Value": "yy" },
{ "Metric": "EEE", "Weight": 15, "Value": "zz" },
{ "Metric": "FFF", "Weight": 25, "Value": "cc" },
];
React.useEffect(() => {
setSelected(Tmp_Selected);
setNonSelected(Tmp_NonSelected);
}, [location]);
There is a function which gets passed just Metric
and Weight
related values. Based on that I need to move each object which matches both criteria from the NonSelected
to the Selected
array.
const MoveValues = (Metric='DDD', Weight=5) => {
}
The expected result for the above two default measures is equal to this ...
const Tmp_Selected = [
{ "Metric": "AAA", "Weight": 10, "Value": "xxx" },
{ "Metric": "BBB", "Weight": 20, "Value": "xx1" },
{ "Metric": "CCC", "Weight": 30, "Value": "xx2" },
{ "Metric": "DDD", "Weight": 5, "Value": "yy" },
];
const Tmp_NonSelected = [
{ "Metric": "EEE", "Weight": 15, "Value": "zz" },
{ "Metric": "FFF", "Weight": 25, "Value": "cc" },
];
The feature the OP actually relies on for solving the task is an array mutating reject
functionality.
Such a function (or method) does accept a callback similar to filter
, where the callback's parameters are item, idx, arr, ...
, and its return value is expected to be a boolean type or at least truthy/falsy. Upon the result of each invocation of the callback, while iterating the to be operated array entirely, a reject
implementation will splice
each matching item from the operated array, thus mutating the latter. Each spliced item gets collected in the implementation's result
array which also is the reject
function's return value.
Thus, a possible implementation of the OP's moveValues
function can be accomplished as easy as this ...
const tmpSelected = [
{ "Metric": "AAA", "Weight": 10, "Value": "xxx" },
{ "Metric": "BBB", "Weight": 20, "Value": "xx1" },
{ "Metric": "CCC", "Weight": 30, "Value": "xx2" },
];
const tmpNonSelected = [
{ "Metric": "DDD", "Weight": 5, "Value": "yy" },
{ "Metric": "EEE", "Weight": 15, "Value": "zz" },
{ "Metric": "DDD", "Weight": 5, "Value": "aa" },
{ "Metric": "FFF", "Weight": 25, "Value": "cc" },
{ "Metric": "DDD", "Weight": 5, "Value": "bb" },
];
const moveItems = (metric, weight) => {
tmpSelected
.push(
...reject(tmpNonSelected, item => {
return item.Metric === metric && item.Weight === weight;
}),
);
};
moveItems('DDD', 5);
console.log({ tmpSelected, tmpNonSelected });
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
function reject(target, condition) {
const result = [];
let idx = target.length;
const copy = [...target];
// - Processing the `target` array from RIGHT to LEFT
// keeps the `idx` always in sync with both related
// array items, the one of the mutated and also the
// one of the unmutated `copy` of the processed array
// reference.
// - Thus, `condition` always gets passed the unmutated
// shallow `copy`.
while (idx) {
if (
// - take a *sparse array* into account.
target.hasOwnProperty(--idx) &&
// - keep processing the unmutated array.
condition(copy[idx], idx, copy)
) {
// - keep filling the `result` array with each
// *rejected* item FROM its LEFT side while
// mutating the `target` array.
result.unshift(target.splice(idx, 1)[0]);
}
}
// - returns an array of rejected items, but not the
// processed and mutated `target` array reference.
return result;
}
</script>