0

Suppose I have an array of object as,

const sampleArray = [ {name: 'Arthur',details: [ {"book":["harry pottar","lotr","something"]} ,{"book":["omega","beta","simba"]} ] },
                     {name: 'simmone',details: [ {"book":["ronjan","pirates"]} ,{"book":["musical","eskobar","elsa"]} ]} ]

I want output as based on total length of book, sort object.

O/P:  [ {name: 'simmone',details: [ {"book":["ronjan","pirates"]} ,{"book":["musical","eskobar","elsa"]} ]}, 
        {name: 'Arthur',details:  [ {"book":["harry pottar","lotr"]} ,{"book":["omega","beta","simba"]} ]} ]

For this I calculated the total length of each book, as,

const bookDetails = sampleArray.map(i => i.book);

const emptyArray = bookDetails.map(
   subarr => subarr.reduce((a, b) => a + b.book.length, 0)
);

It gives me the length of book as [6,5], on basis of book count how can I sort the object as:

O/P:  [ {name: 'simmone',details: [ {"book":["ronjan","pirates"]} ,{"book":["musical","eskobar","elsa"]} ]}, 
        {name: 'Arthur',details:  [ {"book":["harry pottar","lotr"]} ,{"book":["omega","beta","simba"]} ]} ]

If anyone needs any further information, please let me know

9
  • Do you want to sort details array or the sampleArray Commented Apr 16, 2021 at 0:44
  • 1
    I want to sort sampleArray based on total length of book for each object. Commented Apr 16, 2021 at 0:47
  • 1
    Both have 5 books, so how you have sorted accordingly in desired output Commented Apr 16, 2021 at 0:54
  • 1
    "harry pottar","lotr", "omega","beta","simba". There are total 5 books Commented Apr 16, 2021 at 0:58
  • 1
    5 and 6 are books count not the length of the the tittles sum ! Commented Apr 16, 2021 at 1:28

3 Answers 3

3

You could use customized sort to achieve this result. But it is highly inefficient because it is calculating the length of the books each and every time when customizing algorithm place element before and after. Better optimized version added below.

const sampleArray = [{
    name: "Arthur",
    details: [{
        book: ["harry pottar", "lotr", "something"]
      },
      {
        book: ["omega", "beta", "simba"]
      },
    ],
  },
  {
    name: "simmone",
    details: [{
        book: ["ronjan", "pirates"]
      },
      {
        book: ["musical", "eskobar", "elsa"]
      },
    ],
  },
];

function getBookLength(arr) {
  return arr.reduce((acc, curr) => acc + curr.book.length, 0);
}

const result = sampleArray.sort((a, b) => {
  return getBookLength(a.details) - getBookLength(b.details);
});

console.log(result);

FOR BETTER PERFORMANCE: It would be better to store the length of the array so that we don't have to calculate each and every time

const sampleArray = [
  {
    name: "Arthur",
    details: [
      { book: ["harry pottar", "lotr", "something"] },
      { book: ["omega", "beta", "simba"] },
    ],
  },
  {
    name: "simmone",
    details: [
      { book: ["ronjan", "pirates"] },
      { book: ["musical", "eskobar", "elsa"] },
    ],
  },
];

const lengthDict = sampleArray.reduce((acc, { name, details }) => {
  const length = details.reduce((a, b) => a + b.book.length, 0);
  acc[name] = length;
  return acc;
}, {});

const result = sampleArray.sort((a, b) => {
  return lengthDict[a.name] - lengthDict[b.name];
});

console.log(result);

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

1 Comment

Performance to turn * n into constant for time complexity. That's good.
1

If you can do that, then you got everything you want, but you need to understand Sorting algorithm. I see that you didn't specify the direction of the sorting, like less books first, or more book first. But suppose we need More Books first:

const sortedArray = array.sort((elem1, elem2) => {
    // Return less than 0 to keep elem1 before elem2
    // Return greater than 0 to put elem2 before elem1
    // Return 0 to keep as is, regarding the rest of elements
    if (elem1.length > elem2.length) {
        return -1;
    } else if (elem1.length < elem2.length) {
        return 1;
    }
    return 0;
});

Apply your reduce algorithm and you're good. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Comments

1

this way :

const sampleArray = 
  [ { name: 'Arthur', details: 
      [ { book: [ 'harry pottar', 'lotr', 'something'] } 
      , { book: [ 'omega', 'beta', 'simba'] } 
      ] } 
  , { name: 'simmone', details: 
      [ { book: [ 'ronjan', 'pirates'] } 
      , { book: [ 'musical', 'eskobar', 'elsa'] } 
  ] } ] 

const booksCnt =({details})=>details.reduce((s,{book})=>s+book.length ,0)


sampleArray.sort((a,b)=>booksCnt(a)-booksCnt(b))

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

With the decpk optimization :

const sampleArray = 
  [ { name: 'Arthur', details: 
      [ { book: [ 'harry pottar', 'lotr', 'something'] } 
      , { book: [ 'omega', 'beta', 'simba'] } 
      ] } 
  , { name: 'simmone', details: 
      [ { book: [ 'ronjan', 'pirates'] } 
      , { book: [ 'musical', 'eskobar', 'elsa'] } 
  ] } ] 

const booksCnt = ({details})=>details.reduce((s,{book})=>s+book.length ,0)

const NamesLens = Object.fromEntries(sampleArray.map(el=>([el.name,booksCnt(el)])) )

sampleArray.sort((a,b)=>NamesLens[a.name]-NamesLens[b.name] )

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

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.