Morten Vestergaard
Morten Vestergaard

Reputation: 27

How to sort an array of objects containing different information about newspaper articles?

I am trying to boil down an array of objects containing different information about newspaper articles. What I want is a string that summarise the information about each news source.

Each object contains the properties medium, pageNumber and day. The medium will always have a string value, but the pageNumber and day properties can either be a string or null.

Example 1: Where the day property is null

[
  { medium: "The New York Times", pageNumber: "6", day: null },
  { medium: "The New York Times", pageNumber: "12", day: null },
  { medium: "The Wall Street Journal", pageNumber: "6", day: null },
  { medium: "USA Today", pageNumber: "15", day: null },
  { medium: "USA Today", pageNumber: "8", day: null },
  { medium: "USA Today", pageNumber: "32", day: null },
  { medium: "Daily Mail", pageNumber: "12", day: null },
  { medium: "Huffington Post", pageNumber: null, day: null }
]

The desired output:

"The New York Times, page 6, 12; The Wall Street Journal, page 6; USA Today, page 8, 15, 32; Daily Mail, page 12; Huffington Post"

Example 2: Where the day property has a value

[
  { medium: "The New York Times", pageNumber: "6", day: "saturday" },
  { medium: "The New York Times", pageNumber: "12", day: "monday" },
  { medium: "The Wall Street Journal", pageNumber: "6", day: "sunday" },
  { medium: "USA Today", pageNumber: "15", day: "monday" },
  { medium: "USA Today", pageNumber: "8", day: "monday" },
  { medium: "USA Today", pageNumber: "32", day: "saturday" },
  { medium: "Daily Mail", pageNumber: "12", day: "sunday" },
  { medium: "Huffington Post", pageNumber: null, day: "sunday" }
]

The desired output:

"The New York Times, saturday, page 6, monday, page 12; The Wall Street Journal, monday, page 6; USA Today, saturday, page 32; monday, page 8, 15; Daily Mail, sunday, page 12; Huffington Post, monday"

Please note that the pageNumber property value will be null if the medium is not physical (If It's not a real physical newspaper but a web medium with no page numbers). in that case, it should just be omitted. Also note, that if there are multiple page numbers for one medium, they should be sorted from lowest to highest.

The output should be a string. Every medium should only be represented once in the output.

I hope this all makes sense.. I have been trying to wrap my head around this for a few days now, but I just can't find a solution to the problem.

Upvotes: 0

Views: 97

Answers (2)

loop
loop

Reputation: 973

The weekdays are not sorted, though.

const references1 = [
  { medium: "The New York Times", pageNumber: "6", day: null },
  { medium: "The New York Times", pageNumber: "12", day: null },
  { medium: "The Wall Street Journal", pageNumber: "6", day: null },
  { medium: "USA Today", pageNumber: "15", day: null },
  { medium: "USA Today", pageNumber: "8", day: null },
  { medium: "USA Today", pageNumber: "32", day: null },
  { medium: "Daily Mail", pageNumber: "12", day: null },
  { medium: "Huffington Post", pageNumber: null, day: null }
];

const references2 = [
  { medium: "The New York Times", pageNumber: "6", day: "saturday" },
  { medium: "The New York Times", pageNumber: "12", day: "monday" },
  { medium: "The Wall Street Journal", pageNumber: "6", day: "sunday" },
  { medium: "USA Today", pageNumber: "15", day: "monday" },
  { medium: "USA Today", pageNumber: "8", day: "monday" },
  { medium: "USA Today", pageNumber: "32", day: "saturday" },
  { medium: "Daily Mail", pageNumber: "12", day: "sunday" },
  { medium: "Huffington Post", pageNumber: null, day: "sunday" }
];

const summarize = arr => Object.entries(arr.reduce( (acc, reference) => {
    // Map the attributes into a hieararchy.
    ((acc[reference.medium]||={})[reference.day||'']||=[]).push(reference.pageNumber);
    return acc;
  }, {}))
  .map(([medium, references]) => { // Handle each medium separately.
    const details = Object.entries(references).map(([day, pageNumbers]) => {
      // Sort the page numbers ignoring nulls.
      pageNumbers = pageNumbers.filter(v=>v).sort((a,b)=>a-b);
      return day + ( pageNumbers.length 
        ? (day ? ', ': '') + 'page ' + pageNumbers.join(', ') 
        : '' );
    }).join(', ')
    return medium + (details ? ', '+details : '');
  }).join('; ');

console.log(summarize(references1));
console.log(summarize(references2));

Upvotes: 1

Junaid Hamza
Junaid Hamza

Reputation: 179

If you are using lodash library, you can achieve this easily. If not, you can write pure javascript functions as replacements for lodash functions used in below answer.

I hope this will at least give you some direction in how to solve for this use case.

const getSummary = (posts) => {
  let summary = '';
  const groupedByMedium = _.groupBy(posts, 'medium');
  _.map(groupedByMedium, (posts, medium) => {
    if (summary.length > 0) {
        summary += '; ';
    }

    summary += medium;
    
    postsGroupedDay = _.groupBy(posts, 'day');

    _.map(postsGroupedDay, (dayPosts, day) => {
        const pages = _.join(_.sortedUniq(_.map(dayPosts, p => (p.pageNumber))), ', ');

        if (summary.length > 0 && (pages.length > 0 || day !== 'null')) {
            summary += ', ';
        }

        if (day !== 'null') {
            summary += day;
            if (pages.length > 0) {
              summary += ', ';
            }
        }
        
        if (pages.length > 0) {
          summary += `page ${pages}`;
        }
    });
  });

  return summary;
}

Your implementation:

const ex1 = [
  { medium: "The New York Times", pageNumber: "6", day: null },
  { medium: "The New York Times", pageNumber: "12", day: null },
  { medium: "The Wall Street Journal", pageNumber: "6", day: null },
  { medium: "USA Today", pageNumber: "15", day: null },
  { medium: "USA Today", pageNumber: "8", day: null },
  { medium: "USA Today", pageNumber: "32", day: null },
  { medium: "Daily Mail", pageNumber: "12", day: null },
  { medium: "Huffington Post", pageNumber: null, day: null }
];

getSummary(ex1);

Output: The New York Times, page 6, 12; The Wall Street Journal, page 6; USA Today, page 15, 8, 32; Daily Mail, page 12; Huffington Post

const ex2 = [
  { medium: "The New York Times", pageNumber: "6", day: "saturday" },
  { medium: "The New York Times", pageNumber: "12", day: "monday" },
  { medium: "The Wall Street Journal", pageNumber: "6", day: "sunday" },
  { medium: "USA Today", pageNumber: "15", day: "monday" },
  { medium: "USA Today", pageNumber: "8", day: "monday" },
  { medium: "USA Today", pageNumber: "32", day: "saturday" },
  { medium: "Daily Mail", pageNumber: "12", day: "sunday" },
  { medium: "Huffington Post", pageNumber: null, day: "sunday" }
];

getSummary(ex2);

Output: The New York Times, saturday, page 6, monday, page 12; The Wall Street Journal, sunday, page 6; USA Today, monday, page 15, 8, saturday, page 32; Daily Mail, sunday, page 12; Huffington Post, sunday

Upvotes: 1

Related Questions