2

As an input, I get a master list containing child lists (with variable count).

masterList = [[23,12],[34,21],[25,20]]

Number of child lists varies. 3 child lists are shown here, but the number can vary.
I wish to get max of first records and min of second records.
In this case, I know I can hard code like this...

maxNum = max(masterList[0][0], masterList[1][0], masterList[2][0])

How do I write a module for accepting masterList with varying number of child lists and getting max, min?

Thanks.

Vineet
  • 624
  • 1
  • 11
  • 26

7 Answers7

8

You can use zip:

masterList = [[23,12],[34,21],[25,20]]
first, second = zip(*masterList)
print(max(first))
print(min(second))

Edit: for data with sublists containing more than two elements, you can use Python3 unpacking to account for the rest:

masterList = [[23,12, 24],[34,21, 23],[25,20, 23, 23]]
first, second, *_ = zip(*masterList)
print(max(first))
print(min(second))

Output:

34
12
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
3

You can use a generator in order to extract the relevant element of each inner list.

max(innerList[0] for innerList in masterList)

min(innerList[1] for innerList in masterList)
Gabriel
  • 1,922
  • 2
  • 19
  • 37
  • I had thought about this. But wouldn't it create 2 more lists? My data is huge in size. What is your opinion? – Vineet Apr 11 '18 at 14:50
  • @Vineet Nope. It creates a generator (not a new `list` object) that iterates over the original list. No wasted memory. – Gabriel Apr 11 '18 at 15:59
  • @Vineet It only creates a new `list` object if you put the comprehension between `[` and `]`, e.g. `max([innerList[0] for innerList in masterList])` – Gabriel Apr 11 '18 at 16:00
  • @Vineet I've edited my answer to correct the term (it's a _generator_, not _list comprehension_). Also you can read the answers of the following question to better understand the difference: https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehension/47793 – Gabriel Apr 12 '18 at 12:35
3

I suppose you are looking for a way to get the max of all 0th index and the min of all the 1st index elements.

max_of_first_element = max(masterList, key = lambda x:x[0])[0]
min_of_second_element = min(masterList, key = lambda x:x[1])[1]

if you need the min not for the second element but for the last element always, then :

min_of_last_element = min(masterList, key = lambda x:x[-1])[-1]

Hope this solves your problem.

Kenstars
  • 662
  • 4
  • 11
1

To get the max/min of all first/second elements of your child lists, you can do this:

maxNum = max(childlist[0] for childList in masterList)
minNum = min(childlist[1] for childList in masterList)
Patric
  • 1,489
  • 13
  • 28
  • I had thought about this. But wouldn't it create 2 more lists? My data is huge in size. What is your opinion? – Vineet Apr 11 '18 at 14:56
  • Yes you are right, this would create 2 new lists which is actually not necessary. It is better to omit the square brackets, then generators are used. I adjusted my answer accordingly. – Patric Apr 12 '18 at 12:56
1

If you are happy using a 3rd party library, use numpy.

This is efficient for larger arrays versus list-based methods.

import numpy as np

A = np.array([[23,12],[34,21],[25,20]])

res = A[:, 0].max(), A[:, 1].min()

# (34, 12)

This solution handles any length of lists / sublists in a vectorised fashion. The only requirement is that each sublist is the same length.

Related: Why NumPy instead of Python lists?

jpp
  • 159,742
  • 34
  • 281
  • 339
  • thanks @jpp. But when the need can be satisfied very well using built in generator, why to go for 3rd party lib – Vineet Apr 13 '18 at 04:47
  • @Vineet, see update. One analogy is using a grill to toast your bread instead of a purpose-built toaster. Yes, it works, but it's inefficient. – jpp Apr 13 '18 at 08:29
1

You can also try :

import operator
max(masterList, key=operator.itemgetter(1))[0]
#34
min(masterList, key=operator.itemgetter(1))[1]
#12
Sruthi
  • 2,908
  • 1
  • 11
  • 25
  • From the question they need `get max of first records` so it should be `max...itemgetter(0)` right? – Abdul Niyas P M Apr 11 '18 at 14:31
  • 1
    @ABDULNIYASPM `operator.itemgetter(1)` will give you a function that grabs the `first item` from a list-like object. – Sruthi Apr 11 '18 at 14:32
  • `operator.itemgetter(1)` will return the second item from the list as the index starts from zero. – Abdul Niyas P M Apr 11 '18 at 14:34
  • 1
    @ABDULNIYASPM The way `operator.itemgetter(n)` works is it constructs a callable that assumes an iterable object (e.g. list, tuple, set) as input, and fetches the n-th element out of it. So here calling it with argument 1 or 0 will not matter. It will return a tuple containing the maximum of both the columns. Hence note the subscript at the end `[0]` which means to say show max for only first column (and `[1]` in min means to say show min for only second column). So here `operator.itemgetter(0)` and `operator.itemgetter(1)` will work the same – Sruthi Apr 11 '18 at 14:40
1

you can just use built-in function sort, it doesn't use loops so its an efficient method.

largest = sorted(masterList, reverse=True)[0][0]
smallest = sorted(masterList, key=lambda masterList: masterList[1])[0][1]
Mufeed
  • 3,018
  • 4
  • 20
  • 29