Hi,

i'm new to python and I'm having a problem that I'm not able to solve.

I have the following 2D array:

valuearray = [['A', '21', '45'], ['A', '12', '23'], 
              ['A', '54', '21'], ['A', '15', '54'], 
              ['B', '23', '53'], ['B', '34', '53'], 
              ['B', '32', '54'], ['B', '24', '13'], 
              ['C', '31', '43'], ['C', '42', '54'], 
              ['C', '35', '54'], ['C', '12', '11']]

A  21 45
A  12 23
A  54 21
A  15 54
B  23 53
B  34 53
B  32 54
B  24 13
C  31 43
C  42 54
C  35 54
C  12 11

I need to generate from this array another array that have the unique values of valuearray[0] , the maximum of valuearray[1] for each valuearray[0] and the minimum valuearray[2] for each valuearray[0]

The result would be:

resarray[]

    A  54 21
    B  34 13
    C  42 11

what i tried

    uniquenames = []
    un = []
    for i in range(len(valuearray)):
            un.append(valuearray[i][0])
    uniquenames=uniq(un)

test = []
for ci in range(len(valuearray)):
    for gn in range(len(uniquenames)):
        if(valuearray[ci][0] == uniquenames[gn]):
                      # i don't know what to do here
                      i tried append(valuearray[ci][0] , max(valuearray[ci][1]),min( valuearray[ci][2]))

NOTE: the array might have more than 3 columns and a big number of rows(e.g E, F, G ,...) ... so i need a dynamic result for my problem.

thank you

Edited 4 Years Ago by weblover

Here is one way to do it

from operator import itemgetter
import itertools as itt

valuearray = [['A', '21', '45'], ['A', '12', '23'], 
              ['A', '54', '21'], ['A', '15', '54'], 
              ['B', '23', '53'], ['B', '34', '53'], 
              ['B', '32', '54'], ['B', '24', '13'], 
              ['C', '31', '43'], ['C', '42', '54'], 
              ['C', '35', '54'], ['C', '12', '11']]

result = list()
for key, group in itt.groupby(valuearray, itemgetter(0)):
    # replace valuearray with sorted(valuearray, key=itemgetter(0))
    # if valuearray is not initially sorted.
    u, v = itt.tee(group)
    u, v = max(u, key=itemgetter(1))[1], min(v, key = itemgetter(2))[2]
    result.append((key, u, v))

print result
""" my output -->
[('A', '54', '21'), ('B', '34', '13'), ('C', '42', '11')]
"""

I don't understand which result you want when there are more than 3 columns. What should the extra columns contain in the result ?

An alternative is

result = list()
for key, group in itt.groupby(valuearray, itemgetter(0)):
    u, v = zip(*(t[1:3] for t in group))
    result.append((key, max(u), min(v)))

Edited 4 Years Ago by Gribouillis

this solve my problem, but when i have more than 1 columns (i mean i only need these values but from a list which have more than 3 columns)

A better solution would probably to write a generating function like this one

def extremes(records):
    for key, group in itt.groupby(records, itemgetter(0)):
        M, m = next(group)[1:3]
        for record in group:
            M, m = max(M, record[1]), min(m, record[2])
        yield (key, M, m)

print list(extremes(valuearray))

It's advantages over the previous versions is that it does not store more than one record at a time. The argument can be an iterable (not necessarily a list). For example one could read the records in a file and write the result in another file, and very little memory would be used. It also works if there are more than 3 columns. Notice that the initial data need to be sorted on the key.

Take care that you have strings, not integer values, so '9' would be maximum at column 1 and '10000' would be minimum at column 2.

Comments
important comment

Take care that you have strings, not integer values, so '9' would be maximum at column 1 and '10000' would be minimum at column 2.

Oh yes it is true. Here is the corrected version

def extremes(records):
    for key, group in itt.groupby(records, itemgetter(0)):
        M, m = (int(x) for x in next(group)[1:3])
        for record in group:
            M, m = max(M, int(record[1])), min(m, int(record[2]))
        yield (key, str(M), str(m))

print list(extremes(valuearray))
Comments
thank you
This question has already been answered. Start a new discussion instead.