Home > Software engineering >  Last item on the reduce Method
Last item on the reduce Method

Time:01-25

I have this list of countries:

countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']

I need to resolve following exersice: Use reduce to concatenate all the countries and to produce this sentence: Estonia, Finland, Sweden, Denmark, Norway, and Iceland are north European countries

def sentece(pais,pais_next):

        if pais_next=='Iceland':
            return pais ' and ' pais_next   ' are north European countries'
        else: return pais ', ' pais_next

countries_reduce=reduce(sentece,countries)
print(countries_reduce)

The code run perfect, but if I want to do in general, How I know what is the last element?.

CodePudding user response:

The reduce function doesn't have a way to tell it what to do about the last item, only what to do about the initialization.

There's two general ways to go about it:

  1. Just do simple concatenation with a comma and a space, but only on the first n-1 items of the list, then manually append the correct format for the last item
  2. Change the last item from Iceland to and Iceland are north European countries, then do the concatenation for the full list.

CodePudding user response:

Figuring out which is the last element is a bad idea; any solution that would give you that information would be a royal hack.

Normally, you wouldn't use reduce to solve this at all (repeated concatenation is a form of Schlemiel the Painter's Algorithm, involving O(n²) work, where efficient algorithms can be O(n)), so you'd just use ', '.join, e.g.:

countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']
countries_str = f'{", ".join(countries[:-1])} and {countries[-1]} are north European countries'

or, premodifying countries[-1] to reduce the complexity to the point where an f-string isn't necessary (assuming an Oxford comma is okay):

countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']
countries[-1] = 'and '   countries[-1]  # Put the "and " prefix in front ahead of time
countries_str = ', '.join(countries)   ' are north European countries'

where join is used for the consistent join components, wrapped in an f-string that inserts the last item along with the rest of the formatting.

If you must use reduce, you'd still want to handle the final element separately, either by processing it completely separately at the end, e.g.

from functools import reduce

countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']
countries_str = f'{reduce(lambda x, y: f"{x}, {y}", countries[:-1])} and {countries[-1]} are north European countries'
print(countries_str)

Try it online!

or by manually tweaking it ahead of time so it can be used in a consistent manner (assuming you're okay with the Oxford comma):

from functools import reduce

countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']
countries[-1] = 'and '   countries[-1]  # Put the "and " prefix in front ahead of time
countries_str = f'{reduce(lambda x, y: f"{x}, {y}", countries)} are north European countries'
print(countries_str)

Try it online!

Again, reduce is a bad solution to the problem; str.join (using ', '.join) is a O(n) solution (on CPython, it pre-scans the items to join to compute the final length, then preallocates the complete final str, and copies each input exactly once), where reduce is O(n²) (and unlike an actual loop using =, it can't even benefit from the CPython reference interpreter's implementation detail that sometimes allows concatenation to mutate in-place, reducing the number of data copies).

  • Related