user3106579
user3106579

Reputation: 663

map 2 array of object and populate boolean array

I have this first array, at the end of each item it has numerical value.

const arr = ["abc#1","def#2","z#1", "z#2"]

I have to map it with below array

const arrObj = [{
  name: 'abc'
},{
  name: 'def'
},{
  name: 'z'
}]

to populate a new property value that has boolean in array

result = [{
  name: 'abc',
  value: [true, false]
},{
  name: 'def',
  value: [false, true]
},{
  name: 'z',
  value: [true, true]
}]

I'm stuck at doing multiple iteration but failed to produce above result.

const arr = ["abc#1","def#2","z#1", "z#2"]

let arrObj = [{
  name: 'abc'
},{
  name: 'def'
},{
      name: 'z'
    }]

const raw = arr.map(o => o.split('#')[0])
const key = arr.map(o => o.split('#')[1])

arrObj = arrObj.map(o => {

  console.log('raw', raw)

  if(raw.includes(o.name)) {
    console.log('key', key)
    console.log(o.name)
  }

  return {
    ...o,
    value: []
  }
})

Upvotes: 1

Views: 838

Answers (3)

Andriy
Andriy

Reputation: 15442

Try this (UPDATED) solution:

const arr = ['abc#1', 'def#2', 'z#1', 'z#2', 'anotherName#4'];

const arrObj = [
  { name: 'abc' },
  { name: 'def' },
  { name: 'z' }, 
  { name: 'anotherName' }
];

// find min and max IDs
let minId;
let maxId;
arr.forEach(str => {
  const id = +str.split('#')[1];
  minId = typeof minId === 'undefined' || id < minId ? id : minId;
  maxId = typeof maxId === 'undefined' || id > maxId ? id : maxId;
});

// build array of integers staring from minId to maxId including
const arrSize = maxId - minId + 1;
const booleanArr = Array.from(Array(arrSize)).map((_, i) => minId + i);

const arrMap = arr.reduce((res, curr) => ({
  ...res,
  [curr]: 1
}), {});

const result = arrObj.map(({name}) => ({
  name,
  value: booleanArr.map(i => Boolean(arrMap[`${name}#${i}`]))
}));

console.log(result);

Upvotes: 0

zer00ne
zer00ne

Reputation: 43880

Add the following to each Object of the Array of Objects (objArray):

objArray.forEach(object => object.value = [false, false]);
// ex. value: [false, false]

Then .split() each String of the Array of Strings (strArray) at the hash #

let subArray = string.split('#');
// ex. ["abc", "1"]

Convert the second string into a real index number. Note: this step is unnecessary if the strings were properly numbered -- ex. const strArray = ["abc#0", "def#1", ...]

let index = Number(subArray[1]) - 1;

Iterate through objArray again and set each element within sub-array value to true according to matching object.name and subArray[0] and the corresponding index number.

object.value[index] = true;

Demo

Details are also commented in demo

const strArray = ["abc#1", "def#2", "z#1", "z#2"];
let objArray = [{
  name: 'abc'
}, {
  name: 'def'
}, {
  name: 'z'
}];

/*
Assign each object in objArray defaults to:
value: [false, false]
*/
objArray.forEach(object => object.value = [false, false]);

// Uncomment line below to view in console 
/*
console.log(`~~~~~~~ objArray - initial state ~~~~~~~`);
console.log(JSON.stringify(objArray));
console.log(`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`);
console.log(`~~~~~~~ Sub-arrays from strArray ~~~~~~~`);
*/

for (let string of strArray) {
  /*
  Convert each string of strArray to a subArray:
  ex. ["abc", "1"]
  */
  let subArray = string.split('#');
  // Convert the second string into a real index number
  let index = Number(subArray[1]) - 1;

  for (let object of objArray) {
    /*
    if object name matches the first string of a subArray...
    Change the object value to true at the index previously defined
    */
    if (object.name === subArray[0]) {
      object.value[index] = true;
    }
  }
  // Uncomment line below to view in console 
  //console.log(JSON.stringify(`['${subArray[0]}', '${subArray[1]}'] --> object.value index: ${index}`));
}

console.log(`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`);
console.log(`~~~~~~~~ objArray - final state ~~~~~~~~`);
console.log(JSON.stringify(objArray));
console.log(`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`);


for...of Loops

Note: this is not directly related to answer. This is a reply to a comment below:

but you can't have index in for...ofuser3106579

Refer to this example of the MDN section on .entries() method.

const paragraphs = [...document.querySelectorAll('p')];

for (let [index, paragraph] of paragraphs.entries()) {
  if (index % 2 !== 0) {
    paragraph.style.color = 'tomato';
  }
}

paragraphs.forEach((paragraph, index) => {
  if (index % 2 === 0) {
    paragraph.style.color = 'blue';
  }
});

for (let i = 0; i < paragraphs.length; i++) {
  if (i % 2 !== 0) {
    paragraphs[i].style.backgroundColor = '#000';
  }
}
*>* {
  margin-left: 15px
}

p {
  width: max-content;
  margin-left: 30px
}

main,
h1,
section,
h2,
article,
h3 {
  margin-top: -40px: margin-bottom: -40px;
}

.as-console-wrapper {
  width: 350px;
  min-height: 100%;
  margin-left: 45%;
}
<main>
  <h1>Main</h1>
  <section>
    <h2>Section A</h2>
    <p>Paragraph aa</p>
    <p>Paragraph ab</p>
    <article>
      <h3>Article A1</h3>
      <p>Paragraph A1a</p>
      <p>Paragraph A1b</p>
      <p>Paragraph A1c</p>
    </article>
    <p>Paragraph ac</p>
    <article>
      <h3>Article A2</h3>
      <p>Paragraph A2a</p>
      <p>Paragraph A2b</p>
    </article>
    <p>Paragraph ad</p>
  </section>
  <section>
    <h2>Section B</h2>
    <p>Paragraph ba</p>
    <article>
      <h3>Article B1</h3>
      <p>Paragraph B1a</p>
      <p>Paragraph B1b</p>
      <p>Paragraph B1c</p>
      <p>Paragraph B1d</p>
    </article>
    <p>Paragraph bb</p>
    <p>Paragraph bc</p>
  </section>
</main>

Upvotes: 1

You could do it this way:

const arr = ["abc#1","def#2","z#1", "z#2", "anotherName#4"]
      
const boolLength = arr.reduce((r, x) => {
  const [a, b] = x.split('#');
  return +b > r ? b : r
}, 0);

const tempObject = arr.reduce((r, x) => {

  const [a, b] = x.split('#');

  const array = r[a] || Array.from({length: boolLength}, (x, i) => false)
  array[b - 1] = true;

  return { 
   ...r,
   [a]: array
};

}, {});


const result = Object.keys(tempObject).reduce((r, x) => [
  ...r, 
  {
    name: x,
    value: tempObject[x]
  }
], []);
      
console.log(result);

First, store in boolLength the boolean array max lenght. Then store ìn tempObject an object to prevent repeating name properties. And last, in result compose the array.

Upvotes: 0

Related Questions