1

I have an object of the following type:

const obj =  [
  {
    id:1,
    name:'Admin',
    new: [{text:'text', count:4}],
    old: [],
    ongoing: [{text: 'text1', count:5}]
  }
]

I need to get array with objects if they exist in new, old, ongoing object properties

expected result

[
 {
        "id": 1,
        "level": "new",
        "text": "text" ,
        "count": 4,  
     },
{
        "id": 1,
        "level": "ongoing",
        "text": "text1" ,
        "count": 5,  
     },
]

That is, if arrays of objects are available in the object using the keys new, ongoing, old, I create for each object and add to the array, if the key is empty, then I skip

My solution

let data = []
  
    guidance.map((guidanceEntity) => {

      guidanceEntity?.new?.sort((a, b) => b.count - a.count).slice(0, 1)
                     .map(guidanceItem => {
        data.push(
            {
              id: guidanceEntity.id,
              level: 'new',
              text: guidanceItem.text,
              count: guidanceItem.count,
            },
        )
      })

      guidanceEntity?.ongoing?.sort((a, b) => b.count - a.count).slice(0, 1)
                     .map(guidanceItem => {
        data.push({
          id: guidanceEntity.id,
          level: 'ongoing',
          text: guidanceItem.text,
          count: guidanceItem.count,
        })
      })

      guidanceEntity?.old?.sort((a, b) => b.count - a.count).slice(0, 1)
                     .map(guidanceItem => {
        data.push({
          id: guidanceEntity.id,
          level: 'old',
          text: guidanceItem.text,
          count: guidanceItem.count,
        })
      })
    })
7
  • 2
    so you only need the first item of each sub-array (wrt sorting)? Commented Jun 4, 2021 at 7:45
  • const obj = [ { ... } ]; it looks like you have an array of objects, not an object; can you confirm, please? Commented Jun 4, 2021 at 7:45
  • Yes array of object Commented Jun 4, 2021 at 7:48
  • yes first item from eact sub array with sorting Commented Jun 4, 2021 at 7:48
  • 1
    guidanceEntity?.new?.sort((a, b) => b.count - a.count).slice(0, 1).map(guidanceItem => { ... } does not make a lot of sense; if you want just the first item, you can simply select it with guidanceEntity?.new?.sort((a, b) => b.count - a.count)[0] then, if you have a single item, it makes non sense to use map (the same goes for ongoing and old) Commented Jun 4, 2021 at 7:56

3 Answers 3

2

For each object you can apply a transform like below:

const obj = {
  id: 1,
  name: 'Admin',
  new: [{
    text: 'text',
    count: 4
  }],
  old: [],
  ongoing: [{
    text: 'text1',
    count: 5
  }]
}

const targetKeys = ['new', 'old', 'ongoing']

const transform = o => targetKeys.reduce((acc, curr) => acc.concat(o[curr].length ? {
  id: o.id,
  level: curr,
  text: o[curr][0].text,
  count: o[curr][0].count
} : []), [])

console.log(transform(obj))

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

Comments

1

Go through the new, old and ongoing arrays of each object and get the object with biggest count value. You can do this linearly using reduce instead of sort.

const obj=[{id:1,name:"Admin",new:[{text:"text",count:4}],old:[],ongoing:[{text:"text1",count:5}]}],
    levels = ['new', 'old', 'ongoing'],
    biggest = (arr, key) => arr.reduce((a, b) => a[key] > b[key] ? a : b),
    output = []
    
for (const o of obj) {
  for (const level of levels)
    if (o[level].length)
      output.push({ id: o.id, level, ...biggest(o[level], "count") })
}

console.log(output)

Comments

0

If I understood correctly what you want to achieve, this should do:

const objArr = [{
  id: 1,
  name: 'Admin',
  new: [{
    text: 'text',
    count: 4
  }],
  old: [],
  ongoing: [{
    text: 'text1',
    count: 5
  }]
}]

const data = objArr.reduce((output, item) => {
  /* 
   * for each item in the object array,
   * sort the `new`, `ongoing` and `old` attributes,
   * then select the first element for each
   */
  const newItem = (item.new || []).sort((a, b) => b.count - a.count)[0] || null;
  const ongoingItem = (item.ongoing || []).sort((a, b) => b.count - a.count)[0] || null;
  const oldItem = (item.old || []).sort((a, b) => b.count - a.count)[0] || null;
  
  /*
   * if there is at least one element, either `new` `ongoing` or `old`
   * add the attributes `id` and `level` to the element object,
   * then push it into the output array
   */
  if (newItem || ongoingItem || oldItem) {
    newItem && output.push({ id: item.id, level: 'new', ...newItem });
    ongoingItem && output.push({ id: item.id, level: 'ongoing', ...ongoingItem });
    oldItem && output.push({ id: item.id, level: 'old', ...oldItem });
  }
  
  return output
}, []);

console.log(data)

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.