• Need max values in list of tuples, based on position

    From DFS@21:1/5 to All on Fri Nov 11 02:22:34 2022
    [(0,11), (1,1), (2,1),
    (0,1) , (1,41), (2,2),
    (0,9) , (1,3), (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Pancho@21:1/5 to DFS on Fri Nov 11 10:02:34 2022
    On 11/11/2022 07:22, DFS wrote:

    [(0,11), (1,1),  (2,1),
     (0,1) , (1,41), (2,2),
     (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}



    def build_max_dict( tups):
    dict = {}
    for (a,b) in tups:
    if (a in dict):
    if (b>dict[a]):
    dict[a]=b
    else:
    dict[a]=b
    return(sorted(dict.values()))

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Pancho on Fri Nov 11 12:50:42 2022
    Pancho <Pancho.Jones@proton.me> writes:
    def build_max_dict( tups):
    dict = {}
    for (a,b) in tups:
    if (a in dict):
    if (b>dict[a]):
    dict[a]=b
    else:
    dict[a]=b
    return(sorted(dict.values()))

    Or,

    import itertools
    import operator

    def build_max_dict( tups ):
    key = operator.itemgetter( 0 )
    groups = itertools.groupby( sorted( tups, key=key ), key )
    return set( map( lambda x: max( x[ 1 ])[ 1 ], groups ))

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Fri Nov 11 12:49:37 2022
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the following:


    [(0,11), (1,1), (2,1),
    (0,1) , (1,41), (2,2),
    (0,9) , (1,3), (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

    Do they have to be IN THAT ORDER?

    data = [(0,11), (1,1), (2,1), (0,1) , (1,41), (2,2), (0,9) , (1,3), (2,12)]
    reshape = list(zip(*data))
    result = sorted(reshape[1])[-3:]
    result
    [11, 12, 41]



    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Dennis Lee Bieber on Fri Nov 11 13:53:44 2022
    On 11/11/2022 12:49 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the following:


    [(0,11), (1,1), (2,1),
    (0,1) , (1,41), (2,2),
    (0,9) , (1,3), (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

    Do they have to be IN THAT ORDER?

    Yes.

    data = [(0,11), (1,1), (2,1), (0,1) , (1,41), (2,2), (0,9) , (1,3), (2,12)]
    reshape = list(zip(*data))
    result = sorted(reshape[1])[-3:]
    result
    [11, 12, 41]




    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Pancho@21:1/5 to DFS on Fri Nov 11 19:22:04 2022
    On 11/11/2022 18:53, DFS wrote:
    On 11/11/2022 12:49 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the
    following:


    [(0,11), (1,1),  (2,1),
      (0,1) , (1,41), (2,2),
      (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

        Do they have to be IN THAT ORDER?

    Yes.

    Sets aren't ordered, which is why I gave my answer as a list. A wrongly
    ordered list, but I thought it rude to point out my own error, as no one
    else had. :-)

    Assuming you want numeric order of element[0], rather than first
    occurrence order of the element[0] in the original tuple list. In this
    example, they are both the same.

    Here is a corrected version

    from collections import OrderedDict
    def build_max_dict( tups):
    dict = OrderedDict()
    for (a,b) in tups:
    if (a in dict):
    if (b>dict[a]):
    dict[a]=b
    else:
    dict[a]=b
    return(dict.values())

    This solution giving the answer as type odict_values. I'm not quite sure
    what this type is, but it seems to be a sequence/iterable/enumerable
    type, whatever the word is in Python.

    Caveat: I know very little about Python.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Stefan Ram on Fri Nov 11 14:56:41 2022
    On 11/11/2022 7:50 AM, Stefan Ram wrote:
    Pancho <Pancho.Jones@proton.me> writes:
    def build_max_dict( tups):
    dict = {}
    for (a,b) in tups:
    if (a in dict):
    if (b>dict[a]):
    dict[a]=b
    else:
    dict[a]=b
    return(sorted(dict.values()))

    Or,

    import itertools
    import operator

    def build_max_dict( tups ):
    key = operator.itemgetter( 0 )
    groups = itertools.groupby( sorted( tups, key=key ), key )
    return set( map( lambda x: max( x[ 1 ])[ 1 ], groups ))

    FYI, neither of those solutions work:

    Pancho: 11, 12, 41
    You : 41, 11, 12

    The answer I'm looking for is 11,41,12


    Maybe a tuple with the same info presented differently would be easier
    to tackle:

    orig:
    [(0, 11), (1, 1), (2, 1),
    (0, 1), (1, 41), (2, 2),
    (0, 9), (1, 3), (2, 12)]

    new: [(11,1,1),
    (1,41,2),
    (9,3,12)]

    I'm still looking for the max value in each position across all elements
    of the tuple, so the answer is still 11,41,12.


    Edit: found a solution online: -----------------------------------------------------------------
    x = [(11,1,1),(1,41,2),(9,3,12)]
    maxvals = [0]*len(x[0])
    for e in x:
    maxvals = [max(w,int(c)) for w,c in zip(maxvals,e)]
    print(maxvals)
    [11,41,12]
    -----------------------------------------------------------------

    So now the challenge is making it a one-liner!


    Thanks

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Pancho on Fri Nov 11 15:03:49 2022
    On 11/11/2022 2:22 PM, Pancho wrote:
    On 11/11/2022 18:53, DFS wrote:
    On 11/11/2022 12:49 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the
    following:


    [(0,11), (1,1),  (2,1),
      (0,1) , (1,41), (2,2),
      (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

        Do they have to be IN THAT ORDER?

    Yes.

    Sets aren't ordered, which is why I gave my answer as a list. A wrongly ordered list, but I thought it rude to point out my own error, as no one
    else had. :-)

    Assuming you want numeric order of element[0], rather than first
    occurrence order of the element[0] in the original tuple list. In this example, they are both the same.

    Here is a corrected version

    from collections import OrderedDict
    def build_max_dict( tups):
        dict =  OrderedDict()
        for (a,b) in tups:
            if (a in dict):
                if (b>dict[a]):
                    dict[a]=b
            else:
                dict[a]=b
        return(dict.values())

    This solution giving the answer as type odict_values. I'm not quite sure
    what this type is, but it seems to be a sequence/iterable/enumerable
    type, whatever the word is in Python.

    Caveat: I know very little about Python.


    Thanks for looking at it. I'm trying to determine the maximum length of
    each column result in a SQL query. Normally you can use the 3rd value
    of the cursor.description object (see the DB-API spec), but apparently
    not with my dbms (SQLite). The 'display_size' column is None with
    SQLite. So I had to resort to another way.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Pancho@21:1/5 to Thomas Passin on Fri Nov 11 21:58:17 2022
    On 11/11/2022 20:58, Thomas Passin wrote:
    On 11/11/2022 2:22 PM, Pancho via Python-list wrote:
    On 11/11/2022 18:53, DFS wrote:
    On 11/11/2022 12:49 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the >>>> following:


    [(0,11), (1,1),  (2,1),
      (0,1) , (1,41), (2,2),
      (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

        Do they have to be IN THAT ORDER?

    Yes.

    Sets aren't ordered, which is why I gave my answer as a list. A
    wrongly ordered list, but I thought it rude to point out my own error,
    as no one else had. :-)

    Assuming you want numeric order of element[0], rather than first
    occurrence order of the element[0] in the original tuple list. In this
    example, they are both the same.

    Here is a corrected version

    from collections import OrderedDict
    def build_max_dict( tups):
         dict =  OrderedDict()
         for (a,b) in tups:
             if (a in dict):
                 if (b>dict[a]):
                     dict[a]=b
             else:
                 dict[a]=b
         return(dict.values())

    This solution giving the answer as type odict_values. I'm not quite
    sure what this type is, but it seems to be a
    sequence/iterable/enumerable type, whatever the word is in Python.

    Caveat: I know very little about Python.

    Kindly do not use "dict" as a variable name, since that shadows the
    system's built-in name for a dictionary type.


    Yes, I half suspected it might cause subtle problems, I changed it to d,
    and then I changed it back, senility I guess :-).

    That was one of the things I didn't like about Python. Lack of types and subsequent loss of intellisense is the thing I find hardest to deal with.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Pancho via Python-list on Fri Nov 11 15:58:03 2022
    On 11/11/2022 2:22 PM, Pancho via Python-list wrote:
    On 11/11/2022 18:53, DFS wrote:
    On 11/11/2022 12:49 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 02:22:34 -0500, DFS <nospam@dfs.com> declaimed the
    following:


    [(0,11), (1,1),  (2,1),
      (0,1) , (1,41), (2,2),
      (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

        Do they have to be IN THAT ORDER?

    Yes.

    Sets aren't ordered, which is why I gave my answer as a list. A wrongly ordered list, but I thought it rude to point out my own error, as no one
    else had. :-)

    Assuming you want numeric order of element[0], rather than first
    occurrence order of the element[0] in the original tuple list. In this example, they are both the same.

    Here is a corrected version

    from collections import OrderedDict
    def build_max_dict( tups):
        dict =  OrderedDict()
        for (a,b) in tups:
            if (a in dict):
                if (b>dict[a]):
                    dict[a]=b
            else:
                dict[a]=b
        return(dict.values())

    This solution giving the answer as type odict_values. I'm not quite sure
    what this type is, but it seems to be a sequence/iterable/enumerable
    type, whatever the word is in Python.

    Caveat: I know very little about Python.

    Kindly do not use "dict" as a variable name, since that shadows the
    system's built-in name for a dictionary type.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to DFS on Fri Nov 11 16:43:10 2022
    On 11/11/2022 2:22 AM, DFS wrote:

    [(0,11), (1,1),  (2,1),
     (0,1) , (1,41), (2,2),
     (0,9) , (1,3),  (2,12)]

    The set of values in elements[0] is {0,1,2}

    I want the set of max values in elements[1]: {11,41,12}

    This request is ambiguous. Do you want to get the maximum value for
    each row, and present it in the order of those rows? Your data list
    does not distinguish the rows from the tuples, so that information must
    come from somewhere else. Could it sometimes be different from 3? How
    are we supposed to know?

    Also, as has already been noted in this thread, the result cannot
    literally be a set because sets are not ordered but you insisted that
    the order is important.

    This code allows for different length of rows, and tries to be as clear
    as possible:

    data = [(0,11), (1,1), (2,1),
    (0,1), (1,41), (2,2),
    (0,9), (1,3), (2,12)]

    span = 3 # Change for other row lengths

    d1 = [y for x, y in data] # pick out the 2nd member of each tuple
    # d1: [11, 1, 1, 1, 41, 2, 9, 3, 12]

    groups = []
    for i in range(0, len(d1), span):
    group = []
    for s in range(span):
    group.append(d1[i + s])
    groups.append(group)
    # groups: [[11, 1, 1], [1, 41, 2], [9, 3, 12]]

    maxes = [max(t) for t in groups]
    # maxes: [11, 41, 12]

    This could be condensed, but I recommend keeping it as clear as
    possible. Tricky, condensed code becomes harder to understand as time
    goes by.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Fri Nov 11 19:04:25 2022
    On Fri, 11 Nov 2022 15:03:49 -0500, DFS <nospam@dfs.com> declaimed the following:


    Thanks for looking at it. I'm trying to determine the maximum length of
    each column result in a SQL query. Normally you can use the 3rd value
    of the cursor.description object (see the DB-API spec), but apparently
    not with my dbms (SQLite). The 'display_size' column is None with
    SQLite. So I had to resort to another way.

    Not really a surprise. SQLite doesn't really have column widths -- since any column can store data of any type; affinities just drive it into
    what may be the optimal storage for the column... That is, if a column is "INT", SQLite will attempt to convert whatever the data is into an integer
    -- but if the data is not representable as an integer, it will be stored as
    the next best form.

    123 => stored as integer
    "123" => converted and stored as integer
    123.0 => probably converted to integer
    123.5 => likely stored as numeric/double
    "one two three" => can't convert, store it as a string

    We've not seen the SQL query in question, but it might suffice to use a second (first?) SQL query with aggregate (untested)

    max(length(colname))

    for each column in the main SQL query.

    """
    length(X)

    For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. Since SQLite strings do not normally contain NUL characters, the length(X) function will usually return the total number of characters in the string X. For a blob
    value X, length(X) returns the number of bytes in the blob. If X is NULL
    then length(X) is NULL. If X is numeric then length(X) returns the length
    of a string representation of X.
    """

    Note the last sentence for numerics.


    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Dennis Lee Bieber on Fri Nov 11 21:20:10 2022
    On 11/11/2022 7:04 PM, Dennis Lee Bieber wrote:
    On Fri, 11 Nov 2022 15:03:49 -0500, DFS <nospam@dfs.com> declaimed the following:


    Thanks for looking at it. I'm trying to determine the maximum length of
    each column result in a SQL query. Normally you can use the 3rd value
    of the cursor.description object (see the DB-API spec), but apparently
    not with my dbms (SQLite). The 'display_size' column is None with
    SQLite. So I had to resort to another way.

    Not really a surprise. SQLite doesn't really have column widths --

    As I understand it, the cursor.description doesn't look at the column
    type - it goes by the data in the cursor.


    since any column can store data of any type; affinities just drive it into what may be the optimal storage for the column... That is, if a column is "INT", SQLite will attempt to convert whatever the data is into an integer
    -- but if the data is not representable as an integer, it will be stored as the next best form.

    Yeah, I don't know why cursor.description doesn't work with SQLite; all
    their columns are basically varchars.


    123 => stored as integer
    "123" => converted and stored as integer
    123.0 => probably converted to integer
    123.5 => likely stored as numeric/double
    "one two three" => can't convert, store it as a string

    We've not seen the SQL query in question,


    The query is literally any SELECT, any type of data, including SELECT *.
    The reason it works with SELECT * is the cursor.description against
    SQLite DOES give the column names:

    select * from timezone;
    print(cur.description)
    (
    ('TIMEZONE', None, None, None, None, None, None),
    ('TIMEZONEDESC', None, None, None, None, None, None),
    ('UTC_OFFSET', None, None, None, None, None, None)
    )

    (I lined up the data)


    Anyway, I got it working nicely, with the help of the solution I found
    online and posted here earlier:

    -----------------------------------------------------------------
    x = [(11,1,1),(1,41,2),(9,3,12)]
    maxvals = [0]*len(x[0])
    for e in x:

    #clp example using only ints
    maxvals = [max(w,int(c)) for w,c in zip(maxvals,e)] #clp example

    #real world - get the length of the data string, even if all numeric
    maxvals = [max(w,len(str(c))) for w,c in zip(maxvals,e)]

    print(maxvals)
    [11,41,12]
    -----------------------------------------------------------------

    Applied to real data, the iterations might look like this:

    [4, 40, 9]
    [4, 40, 9]
    [4, 40, 9]
    [4, 40, 18]
    [4, 40, 18]
    [4, 40, 18]
    [5, 40, 18]
    [5, 40, 18]
    [5, 40, 18]
    [5, 69, 18]
    [5, 69, 18]
    [5, 69, 18]

    The last row contains the max width of the data in each column.

    Then I compare those datawidths to the column name widths, and take the
    wider of the two, so [5,69,18] might change to [8,69,18] if the column
    label is wider than the widest bit of data in the column

    convert those final widths into a print format string, and everything
    fits well: Each column is perfectly sized and it all looks pleasing to
    the eye (and no external libs like tabulate used either).

    https://imgur.com/UzO3Yhp


    The 'downside' is you have to fully iterate the data twice: once to get
    the widths, then again to print it.

    If I get a wild hair I might create a PostgreSQL clone of my db and see
    if the cursor.description works with it. It would also have to iterate
    the data to determine that 'display_size' value.

    https://peps.python.org/pep-0249/#cursor-attributes




    but it might suffice to use a
    second (first?) SQL query with aggregate (untested)

    max(length(colname))

    for each column in the main SQL query.


    Might be a pain to code dynamically.




    """
    length(X)

    For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. Since SQLite strings do not normally contain NUL characters, the length(X) function will usually return the total number of characters in the string X. For a blob value X, length(X) returns the number of bytes in the blob. If X is NULL
    then length(X) is NULL. If X is numeric then length(X) returns the length
    of a string representation of X.
    """

    Note the last sentence for numerics.



    Thanks for looking at it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Sat Nov 12 15:03:10 2022
    Types are available if you want to use them. https://www.pythontutorial.net/python-basics/python-type-hints/

    From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of Pancho via Python-list <python-list@python.org>
    Date: Friday, November 11, 2022 at 6:28 PM
    To: python-list@python.org <python-list@python.org>
    Subject: Re: Need max values in list of tuples, based on position

    That was one of the things I didn't like about Python. Lack of types and subsequent loss of intellisense is the thing I find hardest to deal with.

    -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!jAUMq5gqI7J7UJIYw7lfpUMAy-BZPyyY8uWLJLVdVLWCaVMSBzVE6uX4RWQ-YZ0c3gvnIYn1u0r0BOmdCvEVAhyK6g$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/
    python-list__;!!Cn_UX_p3!jAUMq5gqI7J7UJIYw7lfpUMAy-BZPyyY8uWLJLVdVLWCaVMSBzVE6uX4RWQ-YZ0c3gvnIYn1u0r0BOmdCvEVAhyK6g$>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From 2QdxY4RzWzUUiLuE@potatochowder.com@21:1/5 to Gerard" on Sat Nov 12 11:09:28 2022
    On 2022-11-12 at 15:03:10 +0000,
    "Weatherby,Gerard" <gweatherby@uchc.edu> wrote:

    Types are available if you want to use
    them. https://www.pythontutorial.net/python-basics/python-type-hints/

    Python has always been a strongly typed language.

    Recent changes have given it some level of static type checking in
    addition to the dyunamic typing.

    From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of Pancho via Python-list <python-list@python.org>
    Date: Friday, November 11, 2022 at 6:28 PM
    To: python-list@python.org <python-list@python.org>
    Subject: Re: Need max values in list of tuples, based on position

    That was one of the things I didn't like about Python. Lack of types and subsequent loss of intellisense is the thing I find hardest to deal with.

    --
    I can eat glass, it does not hurt me.
    Dan Sommers, http://www.tombstonezero.net/dan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Sat Nov 12 13:51:36 2022
    On Sat, 12 Nov 2022 13:24:37 -0500, Dennis Lee Bieber
    <wlfraed@ix.netcom.com> declaimed the following:


    Granted, this will NOT work with "select *" unless one does the select
    */fetchall first, AND extracts the names from the cursor description --
    then run a loop to create the select max(length(col)), ... statement (which >is why I state the fetchall step, as unless one creates a second cursor,
    the latter select will wipe out any unfetched data from the first).


    Okay, a follow-up...


    import sqlite3 as db
    con = db.connect("c:/users/wulfraed/documents/.localdatabases/solitaire-sqlite/solitaire.db")
    cur = con.cursor()
    cur.execute("select * from game")
    <sqlite3.Cursor object at 0x0000022453703F80>
    columns = [ "max(length(%s))" % col[0] for col in cur.description ]
    columns
    ['max(length(ID))', 'max(length(Variant))', 'max(length(Num_of_Decks))', 'max(length(Cards_in_Deck))', 'max(length(Num_Tableau_Cards))', 'max(length(Num_Reserve_Cards))', 'max(length(Foundation_Value))', 'max(length(Tableau_Value))', 'max(length(Reserve_Value))']
    sql = "select %s from game" % ", ".join(columns)
    data = cur.fetchall()
    cur.execute(sql)
    <sqlite3.Cursor object at 0x0000022453703F80>
    widths = cur.fetchone()
    widths
    (1, 16, 1, 2, 2, 2, 1, 2, 2)
    pformat = [ f'%{w}s' for w in widths ]
    pformat
    ['%1s', '%16s', '%1s', '%2s', '%2s', '%2s', '%1s', '%2s', '%2s']
    pformat = " | ".join(pformat)
    for row in data:
    ... print(pformat % row)
    ...
    1 | Klondike draw-3 | 1 | 52 | 28 | 24 | 1 | -1 | -2
    2 | Perpetual Motion | 1 | 52 | 0 | 52 | 1 | -1 | -1
    3 | Klondike draw-1 | 1 | 52 | 28 | 24 | 1 | -1 | -2

    I used " | " rather than "\t" as column separators. View with a fixed width font.

    It could be a tad shorter -- the list-comps for columns and widths (pformat) could be embedded IN the .join() calls.


    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Sat Nov 12 13:24:37 2022
    On Fri, 11 Nov 2022 21:20:10 -0500, DFS <nospam@dfs.com> declaimed the following:

    Yeah, I don't know why cursor.description doesn't work with SQLite; all
    their columns are basically varchars.

    If you read PEP 249 (the general DB-API), everything except column name and data type code are optional. And the documentation for the sqlite3
    module explicitly states that it only provides the column name, not even
    type code.


    The query is literally any SELECT, any type of data, including SELECT *.
    The reason it works with SELECT * is the cursor.description against
    SQLite DOES give the column names:

    select * from timezone;
    print(cur.description)
    (
    ('TIMEZONE', None, None, None, None, None, None),
    ('TIMEZONEDESC', None, None, None, None, None, None),
    ('UTC_OFFSET', None, None, None, None, None, None)
    )

    (I lined up the data)



    Consider (table definition first)

    CREATE TABLE Game (
    ID INTEGER PRIMARY KEY NOT NULL,
    Variant VARCHAR(64) NOT NULL,
    Num_of_Decks INTEGER DEFAULT 1 NOT NULL,
    Cards_in_Deck INTEGER DEFAULT 52 NOT NULL,
    Num_Tableau_Cards INTEGER NOT NULL,
    Num_Reserve_Cards INTEGER
    GENERATED ALWAYS
    AS ((Num_of_Decks * Cards_in_Deck) - Num_Tableau_Cards) STORED,
    Foundation_Value INTEGER DEFAULT 1 NOT NULL,
    Tableau_Value INTEGER DEFAULT -1 NOT NULL,
    Reserve_Value INTEGER DEFAULT -2 NOT NULL
    );
    CREATE UNIQUE INDEX idx_Variant ON Game (Variant);

    followed by a session retrieving three columns...

    import sqlite3 as db
    con = db.connect("c:/users/wulfraed/documents/.localdatabases/solitaire-sqlite/solitaire.db")
    cur = con.cursor()
    cur.execute("""select max(length(variant)), max(length(cards_in_deck)),
    ... max(length(num_reserve_cards)) from Game""")
    <sqlite3.Cursor object at 0x00000246D91E3F80>
    widths = cur.fetchall()
    widths
    [(16, 2, 2)]

    widths[0]
    (16, 2, 2)
    pformat = [f'%{w}s' for w in widths[0] ]
    pformat
    ['%16s', '%2s', '%2s']
    pformat = "\t".join(pformat)
    pformat
    '%16s\t%2s\t%2s'
    for row in cur.fetchall():
    ... print(pformat % row)
    ...
    Klondike draw-3 52 24
    Perpetual Motion 52 52
    Klondike draw-1 52 24


    Granted, this will NOT work with "select *" unless one does the select */fetchall first, AND extracts the names from the cursor description --
    then run a loop to create the select max(length(col)), ... statement (which
    is why I state the fetchall step, as unless one creates a second cursor,
    the latter select will wipe out any unfetched data from the first).

    It lets SQLite do the work of determining the max width occupied by each column, rather than some complicated Python loop.



    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Pancho@21:1/5 to DFS on Sun Nov 13 12:37:10 2022
    On 11/11/2022 19:56, DFS wrote:

    Edit: found a solution online: -----------------------------------------------------------------
    x = [(11,1,1),(1,41,2),(9,3,12)]
    maxvals = [0]*len(x[0])
    for e in x:
        maxvals = [max(w,int(c)) for w,c in zip(maxvals,e)]
    print(maxvals)
    [11,41,12]
    -----------------------------------------------------------------

    So now the challenge is making it a one-liner!


    x = [(11,1,1),(1,41,2),(9,3,12)]
    print(functools.reduce( lambda a,b : [max(w,c) for w,c in zip(a,b)],
    x, [0]*len(x[0])))

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DFS@21:1/5 to Pancho on Sun Nov 13 11:24:31 2022
    On 11/13/2022 7:37 AM, Pancho wrote:
    On 11/11/2022 19:56, DFS wrote:

    Edit: found a solution online:
    -----------------------------------------------------------------
    x = [(11,1,1),(1,41,2),(9,3,12)]
    maxvals = [0]*len(x[0])
    for e in x:
         maxvals = [max(w,int(c)) for w,c in zip(maxvals,e)]
    print(maxvals)
    [11,41,12]
    -----------------------------------------------------------------

    So now the challenge is making it a one-liner!


     x = [(11,1,1),(1,41,2),(9,3,12)]
     print(functools.reduce( lambda a,b : [max(w,c) for w,c in zip(a,b)],
            x, [0]*len(x[0])))

    noice!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)