skip to Main Content

I am trying to write a function that will convert an array that starts with ‘and’ | ‘or’ then process the next elements in the same level until the next ‘and’ | ‘or’. It will be more clear in the following example:

// from
[
  'and',
  1,
  2,
  'or',
  3,
  4,
],

// to
{ and: [
    1,
    2,
    {
        or: [
            3,
            4
        ]
    }
  ]
}

any thoughts?

3

Answers


  1. This can be achieved with the recursive function just like below:

    function convertArrayToObject(arr) {
      let obj = {};
      let currentKey = null;
    
      for (let i = 0; i < arr.length; i++) {
        const item = arr[i];
    
        if (item === 'and' || item === 'or') {
          currentKey = item;
          if (!obj[currentKey]) {
            obj[currentKey] = [];
          }
        } else {
          if (currentKey) {
            if (typeof item === 'object' && item !== null) {
              obj[currentKey].push(convertArrayToObject(item));
            } else {
              obj[currentKey].push(item);
            }
          } else {
            if (typeof item === 'object' && item !== null) {
              obj = convertArrayToObject(item);
            }
          }
        }
      }
    
      return obj;
    }
    

    This method should be called like below

    const arr = ['and', 1, 2, 'or', 3, 4];
    
    const obj = convertArrayToObject(arr);
    
    console.log(obj)  Output: { and: [ 1, 2, { or: [ 3, 4 ] } ] }
    
    Login or Signup to reply.
  2. You can define a helper function and use reduce :

    const arrToObj = (arr) => {
    const operator = arr[0];
    const result = {[operator]: []};
    
    arr.slice(1).reduce((current, val) => {
        if (val === 'and' || val === 'or') {
            return current[current.push({[val]: [] }) - 1][val];
        } else {
            current.push(val);
            return current;
        }
    }, result[operator]);
    
    return result;
    };
    
    
    
    const arr1 = ['and', 1, 2, 'or', 3, 4];
    const obj1 = arrToObj(arr1);
    console.log(obj1);
    
    const arr2 = ['or', 1, 2, 'and', 3, 4];
    const obj2 = arrToObj(arr2);
    console.log(obj2);
    Login or Signup to reply.
  3. Use Array.reduceRight() with a default value of an empty array. Reducing from the right means iterating from the last item to the first.

    If the item is a string, create a new object wrapped in array, with the item as a key, and the current accumulator (acc) as the value. If not prepend the item to the current accumulator array:

    const fn = arr => arr.reduceRight((acc, item) =>
      typeof item === 'string'
      ? [{ [item]: acc }] // create a new object inside a new array
      : [item, ...acc] // prepend the item to the current array
    , [])
    
    const [result] = fn(['and', 1, 2, 'or', 3, 4])
    
    console.log(result)

    If you need a more granular approach (ie – some items may be strings), identify the "and" and "or" values:

    const isOperator = v => v === 'and' || v === 'or'
    
    const fn = arr => arr.reduceRight((acc, v) =>
      isOperator(v)
      ? [{ [v]: acc }] // create a new object inside a new array
      : [v, ...acc] // prepend the item to the current array
    , [])
    
    const [result] = fn(['and', 1, 2, 'or', 3, 4])
    
    console.log(result)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search