0

I'm currently trying to build an addOrUpdate function. Unfortunately I failed several times.

Basically, I have an array of objects. Each object in turn has an array of strings values (and a key valueGroup).

First you have to check if the object exists, if not a new one should be added. If the object already exists, I want to check whether the value I want to insert is already in the object's string array. If not add it. Is it there delete it!

I first tried it functionally via mapper, but I failed completely because I got a double array. Of course, it would be best to solve it completely functionally. Is it possible?

Currently there is no update of the objects. A new object is always inserted, again with an array string containing a new value.

I also find the current code too complicated

I am using Typescript

type SelectedValues = {
    valueGroup: string;
    values: string[];
};

function updateSelectedValues(selectedValues: SelectedValues[], valueGroup: string, value: string): SelectedValues[] {
    // If array empty add first object
    if (selectedValues.length === 0) {
        return [{ valueGroup: valueGroup, values: [value] }];
    } else {
        // look if valueGroup is already there
        const index = selectedValues.findIndex((find) => find.valueGroup === valueGroup);
        if (index === -1) {
            // if no add new valueGroup with first values
            return [...selectedValues, { valueGroup: valueGroup, values: [value] }];
        } else {
            // if valueGroup is there, look if value is already in values
            const findedValues = selectedValues[index];
            if (findedValues.values.includes(value)) {
                // yes, remove value from values
                return [...selectedValues, { ...findedValues, values: findedValues.values.filter((filter) => filter !== value) }];
            } else {
                // no, add value to values
                return [
                    ...selectedValues.filter((object) => object.valueGroup === valueGroup),
                    { ...findedValues, values: [...findedValues.valueGroup, value] },
                ];
            }
        }
    }
}

I always click a button. The button passes the values (valueGroup and value) ​​through the OnClick handler. The array should update itself according to my explanation. Here is an example of how that array could change

//Imagine, after some time we are here. At first it was empty. Two groups were inserted and filled

        type SelectedValues = [
            {
            valueGroup: "valueGroupOne",
            values: ["some", "more", "example", ]
            }, 
            {
            valueGroup: "valueGroupTwo",
            values: ["ddd", "sss", "aaa", ]
            }
            ]
     
    // And new group 
    
     type SelectedValues = [
            {
            valueGroup: "valueGroupOne",
            values: ["some", "more", "example", ]
            }, 
            {
            valueGroup: "valueGroupTwo",
            values: ["ddd", "sss", "aaa", ]
            },
             valueGroup: "valueGroupThree",
            values: ["ssss", "dddsd", "adsdas", ]
            }
            ]
    
    // add to an existing Group new value
    
     type SelectedValues = [
            {
            valueGroup: "valueGroupOne",
            values: ["some", "more", "example","newValueadded" ]
            }, 
            {
            valueGroup: "valueGroupTwo",
            values: ["ddd", "sss", "aaa", ]
            },
             valueGroup: "valueGroupThree",
            values: ["ssss", "dddsd", "adsdas", ]
            }
            ]
    
    // delete from existing Group value
    
     type SelectedValues = [
            {
            valueGroup: "valueGroupOne",
            values: ["some", "more", "example" ]
            }, 
            {
            valueGroup: "valueGroupTwo",
            values: ["ddd", "sss", "aaa", ]
            },
             valueGroup: "valueGroupThree",
            values: ["ssss", "dddsd", "adsdas", ]
            }
            ]
maxfromgermany
  • 239
  • 4
  • 17

3 Answers3

1

You were already pretty close, just made some small errors like not filtering out the object you want to update from the array. I did also change it to use find instead of findIndex but it does not make a huge difference.

function updateSelectedValues(selectedValues: SelectedValues[], valueGroup: string, value: string): SelectedValues[] {
    // If array empty add first object
    if (selectedValues.length === 0) {
        return [{ valueGroup: valueGroup, values: [value] }];
    } else {
        // look if valueGroup is already there
        const obj = selectedValues.find((find) => find.valueGroup === valueGroup);
        if (!obj) {
            // if no add new valueGroup with first values
            return [...selectedValues, { valueGroup: valueGroup, values: [value] }];
        } else {
            if (obj.values.includes(value)) {
                // yes, remove value from values
                return [...selectedValues.filter((object) => object.valueGroup !== valueGroup), { ...obj, values: obj.values.filter((filter) => filter !== value) }];
            } else {
                // no, add value to values
                return [
                    ...selectedValues.filter((object) => object.valueGroup !== valueGroup),
                    { ...obj, values: [...obj.values, value] },
                ];
            }
        }
    }
}

The above shows where you went wrong in your implementation. However we could simplify it to be this:

function updateSelectedValuesLight(selectedValues: SelectedValues[], valueGroup: string, value: string): SelectedValues[] {
    const obj = selectedValues.find((value) => value.valueGroup === valueGroup);

    if (!obj) return [...selectedValues, {valueGroup, values: [value]}]; 

    if (obj.values.includes(value)) {
        obj.values = [...obj.values.filter(iValue => iValue !== value)];
    } else {
        obj.values = [...obj.values, value];
    }

    return selectedValues;
}

This Playground has some tests to see the functionality.

Dean
  • 521
  • 3
  • 14
0

You can achieve this with the help of few JavaScript methods :

  • Array.some() - Used to check if object exist or not based on the key.
  • Array.forEach() - Used to iterate the original array to add/update the value.
  • Array.includes() - Used to check if values array contains the value which we want to insert or not.
  • Array.splice() - Used to remove the value if exist.
  • Array.push() - Used to push the value in values array if not exist / push the object itself if not exist.

Live Demo :

const arr = [{
  valueGroup: 'Group 1',
  values: ['Value 1', 'Value 2']
}, {
  valueGroup: 'Group 2',
  values: ['Value 3', 'Value 4']
}, {
  valueGroup: 'Group 3',
  values: ['Value 5', 'Value 6']
}];

function updateSelectedValues(inputArr, valueGroup, value) {
  const objectExist = inputArr.some(obj => obj.valueGroup === valueGroup);
  if (objectExist) {
    inputArr.forEach(obj => {
      if (obj.valueGroup === valueGroup) {
        obj.values.includes(value) ?
          obj.values.splice(obj.values.indexOf(value), 1) : obj.values.push(value)
      }
    })
  } else {
    arr.push({
      valueGroup: valueGroup,
      values: [value]
    });
  }
  return arr;
}

const result = updateSelectedValues(arr, 'Group 2', 'Value 4');

console.log(result);
Debug Diva
  • 26,058
  • 13
  • 70
  • 123
0

I wrote a function that takes 2 parameters (array with SelectedValues && object with data to add/edit/remove) :

let data = [{ valueGroup: "valueGroupOne", values: ["some", "more", "example", ] }, { valueGroup: "valueGroupTwo", values: ["ddd", "sss", "aaa", ] } ];

function addOrEdit(arr, valueGroup, value) {
    arr = [...arr];
    let valueGroupIdx = arr.findIndex(el => el.valueGroup == valueGroup);

    if(valueGroupIdx > -1) {
        if(arr.at(valueGroupIdx).values.includes(value)) {
            arr[valueGroupIdx].values.splice(arr[valueGroupIdx].values.indexOf(value), 1)
        } else {
            arr[valueGroupIdx].values.push(value)
        } 

    } else {
        arr.push({
            'valueGroup': valueGroup,
            'values': [value],
        });
    }

    return arr;
}

data = addOrEdit(data, 'valueGroupTwo', 'sss');
data = addOrEdit(data, 'valueGroupTwo', 'aaa');
data = addOrEdit(data, 'valueGroupTwo', 'test');
data = addOrEdit(data, 'valueGroupThree', 'one');
data = addOrEdit(data, 'valueGroupThree', 'two');
data = addOrEdit(data, 'valueGroupThree', 'one');


console.log(data);
nem0z
  • 1,060
  • 1
  • 4
  • 17