简体   繁体   中英

arrange values in a python 2D array

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

EDIT: sorry for not presenting 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]))

but append only take one parametre, so I don't know how to continue.

And uniq is a function that gives me the unique values from a list.

We can do this pretty easily with itertools.groupby and zip() :

data = [
    ['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']
]

from itertools import groupby
from operator import itemgetter

for name, values in groupby(data, itemgetter(0)):
    _, first, second = zip(*values)
    print(name, max(first), min(second))

What we are doing here is using groupby() to group the list items by the first item. This gives us three lists - a list for the records beginning with A, then a list for B, then C. It's also worth noting that groupby() doesn't require your list to be sorted.

We then extract the values from these lists by using zip() to unzip the values from a list of triplets into three lists of single values. We throw away the first column as it's just A, B or C as is relevant, and then take the maximum and minimum of the other columns to get the values you wanted.

Which gives us:

A 54 21
B 34 13
C 42 11

Edit:

If you have your values as text, then you can use a list comprehension and str.split() to make a list out of it:

data = """\
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\
"""

data = [value.split() for value in data.split("\n")]

Another Edit:

As per the chat, you can discard extra columns like so:

Python 3.x:

for name, values in groupby(data, itemgetter(0)):
    _, first, second, *_ = zip(*values)
    print(name, max(first), min(second))

Python 2.x:

for name, values in groupby(data, itemgetter(0)):
    first, second = zip(*values)[1:3]
    print name, max(first), min(second)

And to make the output a list, rather than printing the values:

def max_min_by_group(group):
    for name, values in group:
        _, first, second, *_ = zip(*values)
        yield [name, max(first), min(second)]

new = [item for item in max_min_by_group(groupby(data, itemgetter(0)))]

We simply use a list comprehension and a generator (we could do this in one big line but it would be unwieldy and unreadable). This gives us:

[['A', '54', '21'], ['B', '34', '13'], ['C', '42', '11']]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM