My solution in javascript pratice: groceries function

Write a function groceries() that takes an array of object literals of grocery items. The function should return a string with each item separated by a comma except the last two items should be separated by the word 'and'. Make sure spaces (' ') are inserted where they are appropriate.

Examples:

groceries( [{item: 'Carrots'}, {item: 'Hummus'}, {item: 'Pesto'}, {item: 'Rigatoni'}] );
// returns 'Carrots, Hummus, Pesto and Rigatoni'

groceries( [{item: 'Bread'}, {item: 'Butter'}] );
// returns 'Bread and Butter'

groceries( [{item: 'Cheese Balls'}] );
// returns 'Cheese Balls'

My solution:
I dont’t know this solution is an easy way or not. Give some advice please, Thanks!

// Write function below const groceries = arr => { // for single item just return itself if (arr.length === 1) { return arr[0].item; } else if (arr.length === 2){ return arr[0].item + ' and ' + arr[1].item; //for obj have 2 items return 'a' and 'b' } else { let result = ''; //make items link by ',' except the last 2 items for (let i = 0; i < arr.length - 2; i++) { result += arr[i].item + ', ' } result += arr[arr.length - 2].item + ' and ' + arr[arr.length - 1].item; // join the last 2 items return result; } } console.log(groceries( [{item: 'Cheese Balls'}] )) console.log(groceries( [{item: 'Bread'}, {item: 'Butter'}] )) console.log(groceries( [{item: 'Carrots'}, {item: 'Hummus'}, {item: 'Pesto'}, {item: 'Rigatoni'}] ))

It works, so there’s really nothing too wrong with it. There are easier ways of doing this, but they’re things you’d pick up further in your learning or outside of Codecademy. The only thing I’d say is that your comments are inconsistent.

Here’s how I’d do it these days for fun:

const vehicles = ['Motorcycle', 'Bus', 'Car']

const formatArrayAsList = (array, lang, style, type) => (
  new Intl.ListFormat(lang,  { style, type }).format(array)
)

console.log(formatList(vehicles, 'en', 'long', 'conjunction')
// Logs "Motorcycle, Bus, and Car"

If you’re curious how this works, check out: Intl.ListFormat - JavaScript | MDN

If you wanted it to work with an array of objects, you’d just need to create an array of the values of the objects:

const getArrayOfObjectsValues = arrayOfObjects => (
  arrayOfObjects.map(obj => Object.values(obj)).flat()
)

console.log(formatList(getArrayOfObjectsValues(groceryList)))
// Logs 'Carrots, Hummus, Pesto and Rigatoni'
1 Like

Logic looks fine. And, of course, it works!

I suspect you’re bothered by duping the and logic? Or just an intuition?

Here’s a version that uses the current position only to build.

const groceries = arr => {
    let result = '';
    for (let i = 0; i < arr.length; i++) {
        // if it's the last one, just the name
        if (i === arr.length - 1) {
            result += arr[i].item;
        // second to last
        } else if (i === arr.length - 2) {
            result += arr[i].item + ' and ';
        // all other cases: note arr.length === 1 || 2 will never get here
        } else {
            result += arr[i].item + ', '
        }
    }
    return result;
};

And, well, the code golf version:

const groceries = arr => 
    arr.reverse().reduce((acc, x, i) => i === 0 ? x.item : (i === 1 ? `${x.item} and ${acc}` : `${x.item}, ${acc}`), '');
1 Like