Based on a condition, how to remove an item from the processed array and move it to another array?

106 Views Asked by At

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" },
];
4

There are 4 best solutions below

0
Peter Seliger On BEST ANSWER

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>

2
Romeo Razakandriarimanana On
const MoveValues = (Metric = 'DDD', Weight = 5) => {
      const item_Selecteds = NonSelected.filter(item => item.Metric === Metric && item.Weight === Weight)
      const Tmp_Selected = [...Selected, ...item_Selected]
      const Tmp_NonSelected = NonSelected.filter(item => item.Metric !== Metric && item.Weight !== Weight)

      console.log(Tmp_NonSelected)
      console.log(Tmp_Selected)
}
4
Sanmitra Nagaraj On

You can use the filter method of Arrays to remove object from the nonSelected Array.

  1. Find the object to move
  2. remove object from nonSelected array using filter
  3. Add object into selected array using spread operator
  4. setState of both the objects

const MoveValues = (Metric = 'DDD', Weight = 5) => {

    const objectToMove = NonSelected.find(object => object.Metric === Metric && object.Weight === Weight);
  
    if (objectToMove) {

      const arrayOfNonSelected = NonSelected.filter(obj => obj !== objectToMove);
  
      const arrayOfSelected = [...Selected, objectToMove];
  
      setNonSelected(arrayOfNonSelected);
      setSelected(updatedSelected);
    }

  }

3
maulik On

Here is full code of your Component:

    import React, { useEffect } from 'react'

function StackTest() {
    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" },
    ];
    useEffect(() => {
        setSelected(Tmp_Selected);
        setNonSelected(Tmp_NonSelected);
    }, []);

    const MoveValues = (Metric = '', Weight = 0) => {
        const objectToMove = NonSelected.find(object => object.Metric === Metric && object.Weight === Weight);
        // console.log(NonSelected.find(object => object.Metric === Metric && object.Weight === Weight),"objectToMove");
        if (objectToMove) {
            const arrNonSelected = NonSelected.filter(obj => obj !== objectToMove);
            const arrSelected = [...Selected, objectToMove];
            setNonSelected(arrNonSelected);
            setSelected(arrSelected);
        }
    }
    const MoveBackValues = (Metric = '', Weight = 0) => {
        const objectToMove = Selected.find(object => object.Metric === Metric && object.Weight === Weight);
        // console.log(Selected.find(object => object.Metric === Metric && object.Weight === Weight),"objectToMove");
        if (objectToMove) {
            const arrSelected = Selected.filter(obj => obj !== objectToMove);
            const arrNonSelected = [...NonSelected, objectToMove];
            setSelected(arrSelected);
            setNonSelected(arrNonSelected);
        }
    }

    return (
        <>
        <h1>Selected</h1>
        {Selected && Selected.map((item,index) => (
            <p key={index} onClick={(e) => {
                MoveBackValues(item.Metric, item.Weight)
            }
            }>
            {item.Metric} - {item.Value} - {item.Weight}
            <br/></p>
        ))}
        <h1>NonSelected</h1>
        {NonSelected && NonSelected.map((item,index) => (
            <p key={index} onClick={(e) => {
                MoveValues(item.Metric, item.Weight)
            }
            }>
            {item.Metric} - {item.Value} - {item.Weight}
            <br/></p>
        ))}
        </>
    )
}

export default StackTest