0

Hi guys I get confused trying to qcheave this, so any help would be great!

I have two arrays from which I need a specific object. Source arrays:

1-Types (1D):    ['dev', 'env', 'othr']
2-Services (2D): (3) [Array(3), Array(4), Array(6)]
                 Array(3)
                   0: "'1':'Option 11'"
                   1: "'2':'Option 12'"
                   2: "'3':'Option 13'"

                 Array(4)
                   0: "'5':'Option 21'"
                   1: "'6':'Option 22'"
                   2: "'7':'Option 23'"
                   3: "'4':'Option 24'"

                 Array(6)
                   0: "'8':'Option 31'"
                   1: "'9':'Option 32'"
                   2: "'10':'Option 33'"
                   3: "'11':'Option 34'"
                   4: "'12':'Option 35'"
                   5: "'13':'Option 36'"

The desired outcome is this structure:

servData = {
  "dev": {
        "1": "Option 11",
        "2": "Option 12",
        "3": "Option 13"
  },
  "env": {
        "4": "Option 21",
        "5": "Option 22",
        "6": "Option 23",
        "7": "Option 24"
  },
  "othr": {
        "8": "Option 31",
        "9": "Option 32",
        "10": "Option 33",
        "11": "Option 34",
        "12": "Option 35",
        "13": "Option 36"
  }
};
1
  • Regarding all the so far provided answers / solutions are there any questions left? Commented May 2, 2022 at 14:38

4 Answers 4

1

Your data did need some cleanup. NOTE: Data has been updated and .map(a => a.replace(/'/g,'')) has been added to remove all '.

Use Array#map and Array#reduce as follows:

const keys = ['dev', 'env', 'othr'],
      input = [ [ "'1':'Option 11'", "'2':'Option 12'", "'3':'Option 13'" ], [ "'5':'Option 21'", "'6':'Option 22'", "'7':'Option 23'", "'4':'Option 24'" ], [ "'8':'Option 31'", "'9':'Option 32'", "'10':'Option 33'", "'11':'Option 34'", "'12':'Option 35'", "13:'Option 36'" ] ],
      
      output = keys.reduce(
          (o, key,i) => 
          ({
              ...o,
              [key]: input[i].map(a => a.replace(/'/g,'')).reduce(
                  (acc,cur) => 
                  ({...acc,[cur.split(':')[0]]:cur.split(':')[1]}),{})
          }),{}
      );
      
console.log( output );

In order to clean out the ' programmatically, especially the one after : use the following code:

const keys = ['dev', 'env', 'othr'],
      input = [ [ "'1':'Option 11'", "'2':'Option 12'", "'3':'Option 13'" ], [ "'5':'Option 21'", "'6':'Option 22'", "'7':'Option 23'", "'4':'Option 24'" ], [ "'8':'Option 31'", "'9':'Option 32'", "'10':'Option 33'", "'11':'Option 34'", "'12':'Option 35'", "'13':'Option 36'" ] ],
      
      output = input.map(s => s.map(e => e.replace(/'/g,'').split(':')))
      .reduce(
          (o, arr,i) => 
          ({...o, [keys[i]]: arr.reduce((acc,[k,v]) => ({...acc,[k]:v}), {})}),{}
      );
      
console.log( output );

Please note that, as pointed out by @PeterSeliger, replacing ' globally may have unintended consequences. For instance if you had a value such as "'14':'Option's Best'" would become "14:Options Best". So consider a more targetted approach. Maybe use of Function(...)() would avoid the need for replacing all the ''s. See the demo below:

const keys = ['dev', 'env', 'othr'],
      input = [ [ "'1':'Option 11'", "'2':'Option 12'", "'3':'Option 13'" ], [ "'5':'Option 21'", "'6':'Option 22'", "'7':'Option 23'", "'4':'Option 24'" ], [ "'8':'Option 31'", "'9':'Option 32'", "'10':'Option 33'", "'11':'Option 34'", "'12':'Option 35'", "'13':'Option 36'" ] ],
      
      output = input
      .reduce(
          (o, arr,i) => 
          ({
              ...o, 
              [keys[i]]: arr.reduce(
                  (acc,cur) => 
                  ({...acc,...Function(`return {${cur}}`)()}), {})
          }),{}
      );
      
console.log( output );

Sign up to request clarification or add additional context in comments.

2 Comments

You're quite right, thanks. He must have changed from array to object. Will take care of it shortly. .....**DONE**!!
It was actually missing a ' .. the OP is now fixed with the proper '
0

Use this:

const itemNames = ["dev", "env", "othr"];

const items = [
   ["'1':'Option 11'", "'2':'Option 12'", "'3':'Option 13'"],
   ["'5':'Option 21'", "'6':'Option 22'", "'7':'Option 23'", "'4':'Option 24'"],
   [
     "'8':'Option 31'",
     "'9':'Option 32'",
     "'10':'Option 33'",
     "'11':'Option 34'",
     "'12':'Option 35'",
     "'13':'Option 36'"
  ]
];
const value = itemNames
.map((value, index) => ({ index, value }))
.reduce((p, el) => {
  p[el.value] = {};

  items[el.index].forEach((e) => {
    let [op, ...va] = e.split(":");
    op = op.substring(1, op.length - 1);
    va = va.join(":");
    va = va.substring(1, va.length - 1);
    const ar = va;
    p[el.value][parseInt(op)] = ar;
  });

  return p;
}, {});

console.log(value);
.as-console-wrapper { min-height: 100%!important; top: 0; }

2 Comments

Thank you but this produces: ""4": "O:p:t:i:o:n: :2:4"," not '4':'Opetion 24'
@Fallen Angel check now
0

The OP's provided array of stringified entries seems to be mal-formatted ... e.g. "1':'Option 11'", with either a missing or a dispensable single quote for the key part, instead of "'1':'Option 11'" (with single quotes) or "1:'Option 11'" (without single quotes for the key part).

Because of that the beneath presented approach uses a capturing regex like /^'?(?<key>.*?)'?\s*:\s*'?(?<value>.*?)'?$/ in order to sanitize (or rather be agnostic to) each provided string based key-value configuration.

The approach itself makes use of Array.prototype.reduce twice.

The outer reduce does process the list of property or item names as entryKey together with a passed entries-config which features each property name's related array of stringified key-value pairs.

The inner reduce does process such an array, retrieves key and value from the string and, based on this data, assigns a new entry to the value which, within the outer reduce, gets assigned to the newly created entryKey related entry.

function createEntryFromKeyAndEntriesConfig(
  { config = [], result = {} },
  entryKey,
  idx,
) {
  // see ... [https://regex101.com/r/DQbrRM/3]
  const regXKeyValue =
    /^'?(?<key>.*?)'?\s*:\s*'?(?<value>.*?)'?$/;

  result[entryKey] = config[idx]
    .reduce((obj, entryString) => {

      const { key = '', value = '' } = regXKeyValue
        .exec(entryString)
        ?.groups;

      obj[key] = value;
      return obj;
    }, {});

  return { config, result };
}

const entriesConfig = [[
  "1':'Option 11'",
  "2':'Option 12'",
  "3':'Option 13'",
], [
  "5':'Option's 21st'", 
  "6':'Option\'s 22nd'", 
  "7':'Option's 23rd'", 
  "4':'Option\'s 24th'",
], [
  "8':'Option 31'", 
  "9':'Option 32'", 
  "10':'Option 33'", 
  "11':'Option 34'", 
  "12':'Option 35'", 
  "13':'Option 36'",
]];
const propertyNames = ['dev', 'env', 'othr'];

const { result: servData } = propertyNames
  .reduce(createEntryFromKeyAndEntriesConfig, {
    config: entriesConfig,
    result: {},
  });

console.log({ servData });
.as-console-wrapper { min-height: 100%!important; top: 0; }

Comments

0

Try this :

const arr1 = ['dev', 'env', 'othr'];

const arr2 = [["'1':'Option 11'", "'2':'Option 12'", "'3':'Option 13'"],
["'5':'Option 21'", "'6':'Option 22'", "'7':'Option 23'", "'4':'Option 24'"],
["'8':'Option 31'", "'9':'Option 32'", "'10':'Option 33'", "'11':'Option 34'", "'12':'Option 35'", "'13':'Option 36'"]];

const obj = {};

arr1.forEach((item, index) => {
  const innerObj = {};
  arr2[index].forEach(innerItem => {
    innerObj[innerItem.split(':')[0].replace(/['"]+/g, '')] = innerItem.split(':')[1].replace(/['"]+/g, '')
  });
    obj[item] = innerObj;
});

console.log(obj)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.