Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ArcticZombie
Sep 15, 2010

Seventh Arrow posted:

I thought that "l" if you're doing "for l in string_one..." the l is treated as a kind of temporary variable and represents each individual character in string_one. Or am I way off?

You are correct, but seem to be getting confused with indexing/slicing. Let's take a look at your non-working solution:

Python code:
def common_letters(string_one, string_two):
  common = []
  for l in string_one:
    if l in string_one[l] == string_two[l]:
      common.append(l)
  return common
If l is each character of string_one, what are you trying to index both string_one and string_two with? This is what you are trying to do:

Python code:
s = "foobar"
print(s["b"])
Here we are trying to access the "b"th character of the string, that's not an integer, the operation makes no sense.

You always index and slice using integers*, it doesn't make any sense otherwise. Whilst indexing pulls out a single character, slicing pulls out a range of characters; s[1:4] will pull out characters 1 up to (but not including) 4, i.e., "oob".

I've specifically talked about strings here, but indexing/slicing is the same for lists, tuples, etc., just substitute the word "character" above for "element".

* You will see similar square bracket syntax used for pulling the value of a particular key out of a dictionary, but this is neither indexing nor slicing.

ArcticZombie fucked around with this message at 09:33 on Jun 25, 2022

Adbot
ADBOT LOVES YOU

ExcessBLarg!
Sep 1, 2001

Seventh Arrow posted:

The lesson is teaching about iterating over strings, and here is the challenge:
Python code:
from functools import reduce # This bullshit language.

def common_letters(*strs):
  return list(reduce(set.intersection, map(set, strs)))

common_letters("banana", "cream", "asdf") # ['a']
Ruby code:
require 'set' # OK so it's not much better.

def common_letters(*strs)
  strs.map {|s| s.each_char.to_set}.inject(:&).to_a
end

common_letters *%w{banana cream asdf} # ["a"]

ExcessBLarg! fucked around with this message at 13:28 on Jun 26, 2022

Hed
Mar 31, 2004

Fun Shoe
Curious if anyone has recs for parsing libraries that could make the job of what appears to be fixed format column text parsing easier. I would typically just use a big ol' pile of regex and build up things, but maybe there's a better way.

An issue I see with my classic approach is when the tokens collide, like the "WeightPrice" columns below where the values spill into each other with zero spaces.


Two example files below:


pre:
CME FEEDER CATTLE INDEX CALCULATION
Tue, 01/04/22
             1/4/2022         Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large                                                              .
             TUESDAY          #1 Steers         #1 Steers         #1 Steers         #1 Steers         #1-2 Steers       #1-2 Steers       #1-2 Steers       #1-2 Steers                           Weighted                  Weighted
                              700 -749 lbs      750 - 799 lbs     800 - 849 lbs     850 - 899 lbs     700 -749 lbs      750 - 799 lbs     800 - 849 lbs     850 - 899 lbs      Total    Total      Average       Total      Average
Sale DatSale Name         Stat Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head     Weight     Weight        Price       Price
 1/4/22      CLARINDA      IA  197   724  163.17 145   777  159.34 194   820  157.51 239   879  158.71  26   743  153.85  0     0    0.00   0     0    0.00   26   894  144.97  827     667016     806.55     105965055.2    158.86
 1/4/22        CUBA        MO   30  707.33160.30  31  762.61157.86  3    817  155.50  3    862  152.50  3    703  150.00  0     0    0.00   0     0    0.00   0     0    0.00   70    52006.9989   742.96     8225327.146    158.16
 1/4/22       GORDON       NE  221   726  169.29 239   764  163.89  0     0    0.00   8    881  150.50  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   468     350090     748.06     58148285.78    166.10
 1/4/22      IMPERIAL      NE  125   726  167.54 137   776  161.75  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   262     197062     752.15      32400221      164.42
 1/4/22      JACKSON       MO   30   730  162.51  0     0    0.00   3    828  139.00  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   33      24384      738.91       3904245      160.12
 1/4/22     KINGSVILLE     MO  232  730.56167.41 340   769  162.54 216  839.5 164.93  14   852  155.00  22   724  153.79  63   757  166.00  0     0    0.00   14   878  145.25  901   700123.008   777.05     114779255.7    163.94
 1/4/22      LA JUNTA      CO   87   740  164.60  15   780  155.00 107   835  153.00  58   850  156.00  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   267     214725     804.21      33771033      157.28
 1/4/22       MACON        MO  113   725  167.99  28   769  163.82  0     0    0.00   0     0    0.00   20   732  148.56  12   795  142.00  0     0    0.00   0     0    0.00   173     127637     737.79     20819551.39    163.12
 1/4/22     MCALESTER      OK   11   720  148.03  5    772  145.42  2    828  129.51  2    873  122.96  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   20      15182      759.10     2162875.52     142.46
 1/4/22      RIVERTON      WY  370   715  163.02  0     0    0.00   0     0    0.00   0     0    0.00   6    718  146.50  0     0    0.00   0     0    0.00   0     0    0.00   376     268858     715.05      43758063      162.76
 1/4/22       SALINA       KS  188   718  169.77 265  761.54171.43 219   825  164.63  73   880  154.44  55   727  150.20 118   779  158.09  0     0    0.00   42   887  146.44  960   750867.994   782.15     123171847.4    164.04
 1/4/22     UNIONVILLE     MO   83   745  159.55  24   755  166.25  0     0    0.00  372   868  161.16  0     0    0.00   11   766  146.72  4    815  145.00  0     0    0.00   494     414537     839.14     66625106.33    160.72
 1/4/22    WEST PLAINS     MO  194   719  160.60 118  769.66160.56  80   815  156.46  67   861  156.53 111   727  155.24  90   788  154.03  91   835  152.13  5    851  145.00  756   585049.998   773.88     91842167.94    156.98
 1/4/22     WILDORADO      TX   13   727  160.50  55   784  157.75  91  816.29156.39  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   159  126853.9997   797.82     19935953.55    157.16
 1/4/22    DAILY TOTALS       //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5766  4494392.999     779     725508987.84    161.43
 1/4/22  SEVEN-DAY TOTALS     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20007 15831316.03     791      2566732040     162.13
                              BLANK CELLS INDICATE THAT A SALE WAS NOT HELD OR A WEIGHTED AVERAGE REPORT WAS NOT ISSUED     lower case indicates special sale
                                                                                                                                                                                                              Net Change     -0.22

                                                                                                                                                                                                            REPORTED INDEX   162.13

                                                                                                                                                                                                            REPORTED CHANGE  -0.22
pre:
CME FEEDER CATTLE INDEX CALCULATION
Fri, 08/25/17
            8/25/2017         Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large    Medium & Large                                                              .
              FRIDAY          #1 Steers         #1 Steers         #1 Steers         #1 Steers         #1-2 Steers       #1-2 Steers       #1-2 Steers       #1-2 Steers                           Weighted                  Weighted
                              700 -749 lbs      750 - 799 lbs     800 - 849 lbs     850 - 899 lbs     700 -749 lbs      750 - 799 lbs     800 - 849 lbs     850 - 899 lbs      Total    Total      Average       Total      Average
Sale DatSale Location     Stat Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head WeightPrice  Head     Weight     Weight        Price       Price
8/25/17       BELEN        NM   3    703  136.33  2    772  125.51  0     0    0.00   0     0    0.00   4    720  136.74  4    791  132.50  0     0    0.00   0     0    0.00   13       9697        746      1294348.61     133.48
8/25/17   BOWLING GREEN    MO   39   741  145.85  23   768  140.79  7    839  136.50  0     0    0.00   6    732  140.49  11   779  134.78  0     0    0.00   0     0    0.00   86      65397        760      9275460.11     141.83
8/25/17       BRUSH        CO                                                                                                                                                    0        0           0            0          0.00
8/25/17      BURWELL       NE   12   723  151.34  6    780  143.00  0     0    0.00   16   887  139.77  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   34      27548        810      3965881.68     143.96
8/25/17  COLORADO DIRECT   CO   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00    0        0           0            0          0.00
8/25/17      CRAWFORD      NE   36   737  156.10  0     0    0.00   19   837  148.00 108   883  149.25  15   712  153.00  0     0    0.00   0     0    0.00   0     0    0.00   178     148479       834      22362406.2     150.61
8/25/17      CRESTON       IA                                                                                                                                                    0        0           0            0          0.00
8/25/17       DUNLAP       IA                                                                                                                                                    0        0           0            0          0.00
8/25/17     FT. PIERRE     SD                                                                                                                                                    0        0           0            0          0.00
8/25/17      HERREID       SD                                                                                                                                                    0        0           0            0          0.00
8/25/17    IOWA DIRECT     IA   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00    0        0           0            0          0.00
8/25/17   KANSAS DIRECT    KS   0     0    0.00  284   775  144.00 576   828  138.59 195   850  137.50  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00  1055     862778       818      120582476.5    139.76
8/25/17     KNOXVILLE      IA                                                                                                                                                    0        0           0            0          0.00
8/25/17     LEXINGTON      NE                                                                                                                                                    0        0           0            0          0.00
8/25/17   MONTANA DIRECT   MT   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00    0        0           0            0          0.00
8/25/17 NEW MEXICO DIRECT  NM   0     0    0.00  124   775  140.00 290   825  136.80 165   875  134.00  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   579     479725       829       65529650      136.60
8/25/17  OKLAHOMA DIRECT   OK   70   700  146.50 585   750  141.60  0     0    0.00   0     0    0.00   0     0    0.00   62   776  138.50 220   840  137.50  0     0    0.00   937     720662       769       101379012     140.67
8/25/17    sioux center    ia   0     0    0.00   4    791  121.00  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00    4       3164        791        382844       121.00
8/25/17 SOUTH DAKOTA DIREC SD   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00    0        0           0            0          0.00
8/25/17 SUPERIOR VIDEO (SC S   298   710  152.07 663   765  146.05 798   810  141.79 120   875  140.50  68   710  140.00  67   750  135.00 417   805  140.28 393   850  137.25 2824    2238420       793      319134724.9    142.57
8/25/17 SUPERIOR VIDEO (NC N    0     0    0.00  1088  775  144.75 174   839  142.54  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00  1262     989186       784      142862044.4    144.42
8/25/17    TEXAS DIRECT    TX  616   723  142.00 328   773  139.56 247   801  138.96 223   860  131.00 207   722  144.09 895   774  135.23 362   800  134.39  58   850  134.35 2936    2269623       773      311998359.5    137.47
8/25/17 TORRINGTON LIVESTO WY                                                                                                                                                    0        0           0            0          0.00
8/25/17    WY-NE DIRECT    N    0     0    0.00   0     0    0.00   0     0    0.00  400   875  148.42  0     0    0.00   0     0    0.00   0     0    0.00   0     0    0.00   400     350000       875       51947000      148.42
8/25/17    DAILY TOTALS       //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10308   8164679       792     1150714207.93   140.94
8/25/17  SEVEN-DAY TOTALS     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20625   16503832      800     2353826694.67   142.62
                              BLANK CELLS INDICATE THAT A SALE WAS NOT HELD OR A WEIGHTED AVERAGE REPORT WAS NOT ISSUED     lower case indicates special sale
                              Feeder Cattle Index totals for Friday, August 25, 2017 were updated due to a revised report received from Belen, New Mexico                                                     Net Change     -0.62

                                                                                                                                                                                                            REPORTED INDEX   142.62

                                                                                                                                                                                                            REPORTED CHANGE  -0.62

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Why are you using a regex instead of just slicing each input line??

Edit to be a little more helpful: if you know the widths of the columns, then I’d just call readline() in a loop to get each line out as a string and slice each string using the known fixed column widths. If you are already using pandas/don’t mind using it then the read_fwf() function will do that for you.

If you don’t know the column widths and are looking for a ‘smart’ library that can infer the column widths from the file itself then afaik you’re SOL.

DoctorTristan fucked around with this message at 10:07 on Jun 27, 2022

Macichne Leainig
Jul 26, 2012

by VG
Yeah I think this you'd have to write something a bit more bespoke, but I don't see why you couldn't infer the bounds of each column somehow and still parse everything out.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
Boy the fact that it's centered is throwing me off, but I don't think it significantly changes what others are saying.

If the bounds / column widths are consistent from document to document, you can just manually set them once and fuggedaboudit, then just cast to Int for any of the numbers. For example:

code:
ex_str =   "1/4/22      CLARINDA      IA  197   724  163.17 145   777  159.34 194   820  157.51 239   879  158.71  26   743  153.85  0     0  0.00   0     0    0.00   26   894  144.97  827     667016     806.55     105965055.2    158.86"
head = int(ex_str[30:33])
If the column widths are inconsistent, but the column orders are, then you just need to write something to autodetermine the bounds at the beginning, probably by comparing the column headers widths vs the data widths. This gets trickier, but it's still just patternmatching.

12 rats tied together
Sep 7, 2006

awk handles this by collapsing "one or more" of the separator character, which seems like it would work here

you would probably be best served just ignoring the "pretty printed" header and just looking at the column labels themselves. you can generate the headers later from the parsed table data, if you need them

12 rats tied together fucked around with this message at 20:25 on Jun 27, 2022

Gangsta Lean
Dec 3, 2001

Calm, relaxed...what could be more fulfilling?
I highly advise not parsing these tables yourself. Regex is not the answer. Try something like asciitable, it knows how to read many different types of tables. Check out its FixedWidth class, there are example input tables on the project’s homepage.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
Oh hey, asciitable is probably exactly what they were asking for. https://pypi.org/project/asciitable/ for context.

edit: meant to quote, person above me suggested this.

Seventh Arrow
Jan 26, 2005

Things are progressing well so far! In a lot of exercises, I managed to push through and find a solution via searching and thinking through an issue. Sometimes I'm my own worst enemy, as when I do peek at a solution, I find that it was a lot simpler than I thought. There's one puzzler that I found interesting:

It's basically to clean up a list from a legacy system with a lot of artifacts. I've truncated it for legibility:

daily_transactions = ['Edith Mcbride ***$1.21 *** white *** \n09/15/17 ', 'Herbert Tran *** $7.29*** \nwhite&blue*** 09/15/17 ', 'Paul Clarke ***$12.52 \n*** white&blue *** 09/15/17 ', 'Lucille Caldwell \n*** $5.13 *** white *** 09/15/17', '\nEduardo George ***$20.39*** white&yellow \n***09/15/17 ', ' Danny Mclaughlin***$30.82*** \npurple ***09/15/17 ', 'Stacy Vargas*** $1.85 *** \npurple&yellow ***09/15/17', ' Shaun Brock*** \n$17.98***purple&yellow *** 09/15/17']

The idea here was to split it at the "***" so it could be broken up into usable chunks, so this

code:

daily_transactions_split = []
for transaction in daily_transactions:
    daily_transactions_split.append(transaction.split("***"))
print(daily_transactions_split)
gets us this:

[['Edith Mcbride ', '$1.21 ', ' white ', ' \n09/15/17 '], ['Herbert Tran ', ' $7.29', ' \nwhite&blue', ' 09/15/17 '], ['Paul Clarke ', '$12.52 \n', ' white&blue ', ' 09/15/17 '], ['Lucille Caldwell \n', ' $5.13 ', ' white ', ' 09/15/17'], ['\nEduardo George ', '$20.39', ' white&yellow \n', '09/15/17 '], [' Danny Mclaughlin', '$30.82', ' \npurple ', '09/15/17 '], ['Stacy Vargas', ' $1.85 ', ' \npurple&yellow ', '09/15/17'], [' Shaun Brock', ' \n$17.98', 'purple&yellow ', ' 09/15/17']]

I made note that there were lists within the larger list. The next task was to remove the whitespace and this was what I put:

code:
transactions_clean = []
for d_t in daily_transactions_split:
    for w_s in d_t:
        transactions_clean.append(w_s.strip())
print(transactions_clean)
but then I noticed that the 'lists within list' structure was gone!

['Edith Mcbride', '$1.21', 'white', '09/15/17', 'Herbert Tran', '$7.29', 'white&blue', '09/15/17', 'Paul Clarke', '$12.52', 'white&blue', '09/15/17', 'Lucille Caldwell', '$5.13', 'white', '09/15/17', 'Eduardo George', '$20.39', 'white&yellow', '09/15/17', 'Danny Mclaughlin', '$30.82', 'purple', '09/15/17', 'Stacy Vargas', '$1.85', 'purple&yellow', '09/15/17', 'Shaun Brock', '$17.98', 'purple&yellow', '09/15/17']

I thought about this and it made sense because I was really just taking individual items from one list and dumping them into the new list. I didn't know how to fix this, but the solution made good sense:

code:
transactions_clean = []
for d_t in daily_transactions_split:
    transaction_clean = []
    for w_s in d_t:
        transaction_clean.append(w_s.replace("\n", "").strip(" "))
    transactions_clean.append(transaction_clean)

This prettifies it while making it easier to iterate:

[['Edith Mcbride', '$1.21', 'white', '09/15/17'], ['Herbert Tran', '$7.29', 'white&blue', '09/15/17'], ['Paul Clarke', '$12.52', 'white&blue', '09/15/17'], ['Lucille Caldwell', '$5.13', 'white', '09/15/17'], ['Eduardo George', '$20.39', 'white&yellow', '09/15/17'], ['Danny Mclaughlin', '$30.82', 'purple', '09/15/17'], ['Stacy Vargas', '$1.85', 'purple&yellow', '09/15/17'], ['Shaun Brock', '$17.98', 'purple&yellow', '09/15/17']]

I would never have thought of that. There's probably more efficient ways of doing this, but for what's been learned up to this point, it's interesting!

ExcessBLarg!
Sep 1, 2001

Seventh Arrow posted:

There's probably more efficient ways of doing this, but for what's been learned up to this point, it's interesting!
Nested list comprehensions. But once you start doing those the Python folks go "oh, hrm, that's hard to parse, let's go back to manually appending to lists" which is why I have a hard time taking Python seriously as a language.

QuarkJets
Sep 8, 2008

ExcessBLarg! posted:

Nested list comprehensions. But once you start doing those the Python folks go "oh, hrm, that's hard to parse, let's go back to manually appending to lists" which is why I have a hard time taking Python seriously as a language.

I have never, ever seen someone say that. Not even once. More "oh nice list comprehension!" Abandon any amateur hour goobers who are telling you to convert nested list comprehensions into for loops

Macichne Leainig
Jul 26, 2012

by VG
List comprehensions are good IMO.

12 rats tied together
Sep 7, 2006

if you want to end up with the list/dict/set anyway, always use a comprehension.

if you're using the comprehension as a terse way to obtain a specific iteration, and the iteration requires a gnarly looking comprehension, that's when you should consider unrolling. imo.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

QuarkJets posted:

I have never, ever seen someone say that. Not even once. More "oh nice list comprehension!" Abandon any amateur hour goobers who are telling you to convert nested list comprehensions into for loops

I mean...I have seen that, a few times, but that's mostly because nested list comprehensions are a little harder to parse than a non-nested one.

Presto
Nov 22, 2002

Keep calm and Harry on.

QuarkJets posted:

I have never, ever seen someone say that.
Right here. Nested list comprehensions are hideous.

QuarkJets
Sep 8, 2008

Presto posted:

Right here. Nested list comprehensions are hideous.

You’re hideous, and a bad programmer if you really just use append() in a for loop for everything

Presto
Nov 22, 2002

Keep calm and Harry on.
Of course I'm a bad programmer. We're all bad programmers.

Especially people who use nested list comprehensions. :haw:

lazerwolf
Dec 22, 2009

Orange and Black
I’m with Presto. Readable code is better than a fancy one liners. Single list comprehensions are cool and good. Once you go nested I’d rather break it into separate loops for better readability imho.

QuarkJets
Sep 8, 2008

lazerwolf posted:

I’m with Presto. Readable code is better than a fancy one liners. Single list comprehensions are cool and good. Once you go nested I’d rather break it into separate loops for better readability imho.

Oh no one is saying that they have to be one liners. You can and should break up nested list comprehensions into multiple lines, creating code that is easier to read and significantly more performant than nested loops.

QuarkJets
Sep 8, 2008

Heck, a list comprehension with calls to a function that performs another list comprehension would also be preferred to nested for loops.

Macichne Leainig
Jul 26, 2012

by VG
Is two sets of "x for x in y" in a list really that hard to parse? Like yeah if you're nesting together like a dozen comprehensions that'll probably be an unrecognizable mess, but like anything else there's a balance to be struck.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If I have to actually "parse" it mentally to figure out what it does instead of just looking at it and it being obvious, then yeah it's too complicated.

Macichne Leainig
Jul 26, 2012

by VG
I think we're all being too vague to agree on anything, honestly. What's an example of a list comprehension that you would find hard to parse? I'm thinking of something just like:

Python code:
[[x for x in range(5)] for y in range(5)]
This gives us a list of 5 lists where each inner list is [0,1,2,3,4]. I don't know that this is too hard for me to parse, but I don't think I would go any further than something like this personally.

tays revenge
Aug 29, 2009

Protocol7 posted:

Python code:
[[x for x in range(5)] for y in range(5)]

It's fine. People are just bitching because they don't like golf.

Data Graham
Dec 28, 2009

📈📊🍪😋



Otoh, they don't typically have Obfuscated Python Contests.

QuarkJets
Sep 8, 2008

The example earlier was a one-liner, but multi-line list comprehensions are also cool and good. I like to limit line length to 100, I know others who use 120.

Python code:
# for loops
result = []
for i in range(10):
    sub_result = []
    for j in range(15):
        sub_result.append(i*j + j)
    result.append(sub_result)

# list comprehensions
result = [[i*j + j for j in range(15)] 
          for i in range(10)]

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If it's a simple cross-product mapping then sure, list comprehensions are great.

Once you start adding conditionals at multiple levels, that's when things get complex enough that you should consider being more explicit and writing a loop instead.

QuarkJets
Sep 8, 2008

Jabor posted:

If it's a simple cross-product mapping then sure, list comprehensions are great.

Once you start adding conditionals at multiple levels, that's when things get complex enough that you should consider being more explicit and writing a loop instead.

All right let's consider that then:

The example earlier was a one-liner, but multi-line list comprehensions are also cool and good. I like to limit line length to 100, I know others who use 120.

Python code:
# for loops
result = []
for i in range(10):
    sub_result = []
    for j in range(15):
        if (temp := i*j + j) < 50:
            sub_result.append(temp)
    if i*(i-1) < 30:
        result.append(sub_result)

# list comprehensions
result = [[temp for j in range(15) if (temp := i*j + j) < 50] 
          for i in range(10) if i*(i-1) < 30]
This... it seems like this is showing that the list comprehension is still better? Like even better than before, even.

Have even more complicated logic? No problem! That poo poo should be in a function anyway! And lists already naturally support being broken up over multiple lines to help organize the logic!

Python code:
# for loops
result = []
for i in range(10):
    sub_result = []
    for j in range(15):
        if (temp := some_function(i, j)) < 30:
            sub_result.append(temp)
    if some_other_conditional(i):
        result.append(sub_result)

# list comprehensions
result = [[temp for j in range(15)
	   if (temp := some_function(i, j)) < 30] 
          for i in range(10)
	  if some_other_conditional(i)]
All of the conditionals are identical, no differences there. It doesn't matter how complicated they get, they can be written identically in both situations.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If you want an honest comparison then perhaps you should avoid writing the "for loop" version in a really stupid way.

Like maybe instead you could write it something like this:
code:

result = []
for i in range(10):
    if i*(i-1) >= 30:
        continue 
    result.append([val for j in range(15) if (val := i*j + j) < 50])

And then because you've avoided writing it in a stupid way, you can identify that your condition is monotonic - once it starts failing, it will keep failing, so you don't even need to check the rest of the elements:
code:

result = []
for i in range(10):
    if i*(i-1) >= 30:
        break 
    result.append([val for j in range(15) if (val := i*j + j) < 50])

QuarkJets
Sep 8, 2008

Jabor posted:

If you want an honest comparison then perhaps you should avoid writing the "for loop" version in a really stupid way.

Like maybe instead you could write it something like this:
code:
result = []
for i in range(10):
    if i*(i-1) >= 30:
        continue 
    result.append([val for j in range(15) if (val := i*j + j) < 50])

First off, gently caress you, what I wrote wasn't stupid.

Second, I think that the nested comprehension still reads cleaner than this. Providing it again for ease of reference

Python code:
result = []
for i in range(10):
    if i*(i-1) >= 30:
        continue 
    result.append([val for j in range(15) if (val := i*j + j) < 50])
Python code:
result = [[val for j in range(15) if (val := i*j + j) < 50] 
          for i in range(10) if i*(i-1) < 30]

Jabor posted:

And then because you've avoided writing it in a stupid way, you can identify that your condition is monotonic - once it starts failing, it will keep failing, so you don't even need to check the rest of the elements:
code:
result = []
for i in range(10):
    if i*(i-1) >= 30:
        break 
    result.append([val for j in range(15) if (val := i*j + j) < 50])

I just wanted a contrived scenario, if you really wanted to optimize it I think it'd be better to just alter the range rather than use break :shrug:

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Sorry, but this structure:
code:
sub_result = some_completely_non_side_effecting_calculation()
if a_condition_that_could_easily_be_checked_before_doing_the_calculation():
  result.append(sub_result)
Is pretty objectively stupid. If you want to convincingly argue that your approach is superior, you should be comparing your approach to the best possible alternatives, not crazy ones that nobody would really write.

Hughmoris
Apr 21, 2007
Let's go to the abyss!
Rookie question as I try to wrap my head around Docker and containers:

Say I have a new install of Ubuntu and want to try out the latest Python Docker image. Do I develop my script INSIDE the running Python container, or do I develop on my local machine and pass my script as a parameter when I run the container?

Armitag3
Mar 15, 2020

Forget it Jake, it's cybertown.


Hughmoris posted:

Rookie question as I try to wrap my head around Docker and containers:

Say I have a new install of Ubuntu and want to try out the latest Python Docker image. Do I develop my script INSIDE the running Python container, or do I develop on my local machine and pass my script as a parameter when I run the container?

The easiest way is to skip building images everytime with new versions of your script. To do that you bind the dir of your script with -v into a volume the container can reach. The entrypoint command will always be the same too. Then when you spin the container up it will always be the same image just running the script you bound from your host machine.

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Armitag3 posted:

The easiest way is to skip building images everytime with new versions of your script. To do that you bind the dir of your script with -v into a volume the container can reach. The entrypoint command will always be the same too. Then when you spin the container up it will always be the same image just running the script you bound from your host machine.

Maybe dumb ? but what about containers for AWS Lambda where your script goes in the same directory (/var/task) with all your other files?

necrotic
Aug 2, 2005
I owe my brother big time for this!

CarForumPoster posted:

Maybe dumb ? but what about containers for AWS Lambda where your script goes in the same directory (/var/task) with all your other files?

Deployment images would have the script copied in at build time.

ExcessBLarg!
Sep 1, 2001

QuarkJets posted:

Have even more complicated logic? No problem! That poo poo should be in a function anyway! And lists already naturally support being broken up over multiple lines to help organize the logic!
The problem isn't so much that list comprehensions lexically can be split across lines, but that they can only contain expressions. What people want to do is write multiple statements, including variable assignments (walrus operator aside), like you can with regular for loops, and Python doesn't let you do that with list comprehensions without defining a function.

And yes, putting complex logic into a function is good, but when you're defining a set of nested functions and the immediately using them in map calls, I don't know that that's any more clearer than the language just supporting some kind of multi-statement "map-for" or "filter-for" construct.

QuarkJets
Sep 8, 2008

Jabor posted:

Sorry, but this structure:
code:
sub_result = some_completely_non_side_effecting_calculation()
if a_condition_that_could_easily_be_checked_before_doing_the_calculation():
  result.append(sub_result)
Is pretty objectively stupid. If you want to convincingly argue that your approach is superior, you should be comparing your approach to the best possible alternatives, not crazy ones that nobody would really write.

That's what you object to? A contrived detail that was purely used for illustration and is irrelevant to the topic? Okay.

QuarkJets
Sep 8, 2008

ExcessBLarg! posted:

The problem isn't so much that list comprehensions lexically can be split across lines, but that they can only contain expressions. What people want to do is write multiple statements, including variable assignments (walrus operator aside), like you can with regular for loops, and Python doesn't let you do that with list comprehensions without defining a function.

And yes, putting complex logic into a function is good, but when you're defining a set of nested functions and the immediately using them in map calls, I don't know that that's any more clearer than the language just supporting some kind of multi-statement "map-for" or "filter-for" construct.

That's all true, but I'm going to defer to Clean Code on this one: if several statements are needed to determine or calculate what you're putting into a list, then those lines should be in an easily testable function regardless of whichever method of loop creation you prefer.

This does not mean that nested list comprehensions are always right, but the argument was that they're always wrong - that's what I disagree with.

Adbot
ADBOT LOVES YOU

sugar free jazz
Mar 5, 2008

I’m trying to get a package I cloned from github, that doesn’t have a setup.py, imported into a conda env and I have no fuckin idea what to do

Do I just load the dependencies and run the functions and just do it manually or wtf

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply