0

I have the following data in an array.

tempAttachments:Array[2]
  0:Object
    _id:"12345-678910"
    bytes:412051
    file:File
    size:411532
    title:"someFile.csv"
    headers: Array[3]
        0: optionOne
        1: undefined
        2: optionTwo
        3: undefined
        4: undefined
        5: optionThree
    type:"file"
    fileType:"typeOne"
  1:Object
    _id:"9999-2222"
    bytes:12345
    file:File
    size:23456
    title:"anotherFile.csv"
    headers: Array[3]
        0: optionOne
    type:"file"
    fileType:"typeTwo"

There are two elements I am interested in, and that is the _id and headers array. I am trying to end up with something like this

Array
(
  [0] => Array
  (
     [id] => 12345-678910
     [optionOne] => 0
     [optionTwo] => 2
     [optionThree] => 5
  )
  [1] => Array
  (
     [id] => 9999-2222
     [optionOne] => 0
  )
)

So essentially, the id and the index of the three options as these relate to their column in a file. The problem is, a file may have a maximum of three options (using the names above) however, they may only have one or two.

So I have started like this

const payload = {}

this.tempAttachments.forEach(function (attachment, index) {
  payload[index] = {
    id: attachment._id
  }
})

What I am unsure about is how to map the indexes of the options, with the key set as their name, if they exist. What would be the best way to achieve this?

Thanks

4
  • use a map based approach. Commented Jun 27, 2020 at 15:25
  • What is optionOne, optionTwo, ... within the headers array? is it a type? can it somehow be handled as string / transformed in to a string for the expected output part? Commented Jun 27, 2020 at 15:38
  • They are just strings Commented Jun 27, 2020 at 15:39
  • 1
    Please post your data in JSON format so that we can easily use it in tests Commented Jun 27, 2020 at 15:40

3 Answers 3

2

This is an environment/setting for a classic combined approach of map (here: create a new type from each attachment type) and reduce (here: create/collect new option data only for valid header/option items) ...

const tempAttachments = [{
  _id: "12345-678910",
  bytes: 412051,
  file: "File",
  size: 411532,
  title: "someFile.csv",
  headers: [
    "optionOne",
    undefined,
    "optionTwo",
    undefined,
    undefined,
    "optionThree"
  ],
  type:"file",
  fileType:"typeOne"
}, {
  _id: "9999-2222",
  bytes: 12345,
  file: "File",
  size: 23456,
  title: "anotherFile.csv",
  headers: [
    "optionOne"
  ],
  type: "file",
  fileType: "typeTwo"
}];


function collectValidOptionData(collector, optionItem, idx) {
  // if (optionItem != null) {
  //  collector[String(optionItem)] = idx
  // }
  if (typeof optionItem === 'string') {
    collector[optionItem] = idx;
  }
  return collector;
}

function createOptionTypeFromAttachment(attachmentType) {
  return attachmentType.headers.reduce(collectValidOptionData, {
    id: attachmentType._id
  });
}


console.log(
  'tempAttachments.map(createOptionTypeFromAttachment) : ',
  tempAttachments.map(createOptionTypeFromAttachment)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

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

Comments

2

A clean way to do this, is using the Array.map method, it creates a new array from another.

(More Info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)

The code below will convert the tempAttachments to the new format, where is based in this structure:

[
  {
    id: AttachmentID
    optionName: optionIndex
    optionName: optionIndex
    ...
  }
]

It will only add options that have a value, ignoring undefined options.

Solution:

const payload = tempAttachments.map(attachment => {
  const newAttachment = {
    id: attachment._id,
  }

  attachment.headers.forEach((option, index) => {
    if (option) {
      newAttachment[option] = index;
    }
  })

  return newAttachment;
})

2 Comments

I think false and 0.. and other falsy values will not be added.
Yes, any falsy values will be ignored, that includes 0, false, empty strings, undefined, etc. I said specifically undefined because in this case, only strings and undefined are in the array. It's only to facilitate understanding and dosn't overwhelm he with information.
1

Something like this:

const tempAttachments = [{
    _id: "12345-678910",
    bytes: 412051,
    file: 'File',
    size: 411532,
    title: "someFile.csv",
    headers: [
        'optionOne',
        undefined,
        'optionTwo',
        undefined,
        undefined,
        'optionThree'
    ],
    type: "file",
    fileType: "typeOne"
}, {
    _id: "9999-2222",
    bytes: 12345,
    file: 'File',
    size: 23456,
    title: "anotherFile.csv",
    headers: [
        'optionOne',
        'optionTwo',
        'optionThree'
    ],
    type: "file",
    fileType: "typeTwo",
}];

const output = tempAttachments.reduce((akku, item) => {
    let akkuItem = {
        id: item._id,
    };
    item.headers.forEach((value, index) => {
        if(typeof value !== 'undefined') {
            akkuItem[value] = index;
        }
    });
    akku.push(akkuItem);
    return akku;
}, []);
console.log(output);

2 Comments

item.headers is an array. There is no need to process it with Object.entries ... item.headers.forEach already will do. On the other hand it was better to make use of reduce for structures one does want to collect only certain items from (thus reduce instead of forEach). Then again map instead of reduce for the outer structure was the preferable choice for one does want to process/map every attachment type.
You are right, header is not an object.. Have changed the code :) Thanx.

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.