Search code examples
javascriptarraysecmascript-6ecmascript-5

Add complex array of objects into another object


I have an source object obj that looks like this and an array input

const obj = {
  name: "xyz",
  filter: {
    and: [
      {
        or: [
          {
            and: []
          }
        ]
      }
    ]
  }
};

const input = ["test1\name1", "test2\name2"]

I need to push objects that are formed after spiltting input by \. After splitting, using left side of the string i need to form an object like this

{ type: "type1", value: whatever the left hand value}

Same for right side value

{ type: "type2", value: whatever the right hand value}

And these objects should be pushed to innermost and in the source object.

Expected output

{
  name: "xyz",
  filter: {
    and: [
      {
        or: [
          {
            and: [
              { type: "type1", value: "test1" },
              { type: "type2", value: "name1" },
              { type: "type1", value: "test2" },
              { type: "type2", value: "name2" }
            ]
          }
        ]
      }
    ]
  }
}

Code that I tried

function processResult(input) {
  return {
    name: "xyz",
    filter: {
      and: [
        {
          or: [
            {
              and: getUpdatedValues(input)
            }
          ]
        }
      ]
    }
  };
}

// I need the getUpdateValues to be processing the each item from the input array and then sending the two objects back after splitting

function getUpdatedValues(input){
  const updated = input.map(item => {
    const spilt = item.split("\\");
  });
}

Solution

  • Assuming that the input array would include an escape character and could be like so: ["test1\\name1", "test2\\name2"], presented below is one possible way to achieve the desired objective.

    Code Snippet

    const transformMyArr = (myArr) => (
      myArr.flatMap(
        s => {
          const [leftie, rightie] = s.split('\\');
          return ([{
            type: 'type1', value: leftie
          }, {
            type: 'type2', value: rightie
          }]);
        }
      )
    );
    
    /* code explanation
    // method to transform the array to required format
    const transformMyArr = (myArr) => (
      myArr.flatMap(  // iterate over the array and remove nested-array in result
        s => {        // manipulate each array element
          // "split" using "\\" and store the left-side as "type"
          // and the rest as "value"
          const [type, value] = s.split('\\');
          // explicit return of an array with two objects per array elt
          return ([{
            type: 'type1', value: leftie
          }, {
            type: 'type2', value: rightie
          }]);
        }
      )         // implicit return from the "transformMyArr" method
    );
    
    */
    
    let myInputArr = ["test1\\name1", "test2\\name2"];
    
    const myObj = {
      name: "test",
      filter: {
        and: [{
          or: [{
            and: [...transformMyArr(myInputArr) ]
          }]
        }]
      }
    };
    
    console.log('updated obj:\n', myObj);
    .as-console-wrapper { max-height: 100% !important; top: 0 }

    Explanation

    Inline comments added to the snippet above.

    EDIT

    the left and right side value after splitting can be present in different items in the array too. How can I have only unique type1 , type2 objects inside final array

    const myTransform2 = arr => {
      // set-up empty arrays to hold left & right side elements
      let leftEltArr = [], rightEltArr = [];
      // iterate over the arg-array using ".forEach()"
      arr?.forEach(
        s => {
          // split using "\\" to store left & right side elts
          const [leftElt, rightElt] = s.split('\\');
          // push elements into respective arrays
          leftEltArr.push(leftElt);
          rightEltArr.push(rightElt);
        }
      );
      // return the result using left & right arrays
      return (
        ([...new Set(leftEltArr)])      // remove dupes
        .map(value => ({ type: 'type1', value }))   // transform to required format
        .concat(              // concat result of similar operation on right-side
          ([...new Set(rightEltArr)])
          .map(value => ({ type: 'type2', value }))
        )
      );
    };
    
    // updated sample input with 3rd elt which has duplicates
    // on both left-side & right-side of the "\\"
    let myInputArr = ["test1\\name1", "test2\\name2", "test1\\name2"];
    
    const myObj = {
      name: "test",
      filter: {
        and: [{
          or: [{
            and: [...myTransform2(myInputArr) ]
          }]
        }]
      }
    };
    
    console.log('transformed object:\n', myObj);
    .as-console-wrapper { max-height: 100% !important; top: 0 }