1

I have a list of tuples like so:

[('1001794', 'Us/Eastern', '2', '1', '3', '4', '5')
('1001832', 'Us/Central', '2', '3', '4', '4', '5')
('1001848', 'Us/Central', '2', '4', '5', '4', '5')
('1001855', 'Us/Central', '2', '1', '4', '4', '5')
('1001899', 'Us/Central', '2', '1', '4', '3', '5')
('1001914', 'Us/Pacific', '1', '4', '2', '4', '5')
('1001971', 'Us/Pacific', '3', '4', '2', '3', '5')
('1002021', 'Us/Eastern', '2', '1', '4', '4', '5')
('1002026', 'Us/Central', '2', '1', '4', '4', '2')
('1002028', 'Us/Eastern', '2', '1', '4', '4', '5')
('1002041', 'Us/Eastern', '2', '4', '3', '5', '4')]

And I need to convert all the numbers in there to numbers. I don't mind if I have to do 6 different list comprehensions if necessary, but I still can't wrap my head around list comprehension enough to make one from scratch properly. I tried doing:

[x = (int(x[0]),x[1],int(x[2]),int(x[3]),int(x[4]),int(x[5]),int(x[6])) for x in tlist]

But it tells me it's invalid syntax, and I'm not sure why?

cs95
  • 379,657
  • 97
  • 704
  • 746
CapnShanty
  • 529
  • 8
  • 20
  • 2
    Because you're doing an assignment in the list comprehension. Get rid of `x =`. – roganjosh Jan 08 '19 at 20:30
  • and I assume that's not allowed? So list comprehension is not the tool for this then? I don't just want to see them in that format, I want the list to have them in that format – CapnShanty Jan 08 '19 at 20:30
  • 1
    I edited my comment. But the "I'll do 6 comprehensions" doesn't make sense; they are not sufficiently faster than regular `for` loops to justify this kind of approach; don't pursue list comprehensions at the vast expense of sensible code – roganjosh Jan 08 '19 at 20:32
  • No, list comprehensions are perfectly fine for this. But there are no assignment statements in list comprehensions, only expressions are allowed. If you are thikning in terms of assignment, i.e. mutating state, then you shouldn't use list-comprehensions, and just use a regular for loop. But this *could* be a very straightforward list comprehension, no doubt – juanpa.arrivillaga Jan 08 '19 at 20:34
  • okay I'll just do a for loop then, thanks – CapnShanty Jan 08 '19 at 20:34
  • 1
    Why? Youve already been given a working answer. – roganjosh Jan 08 '19 at 20:35
  • Oh when I wrote that comment the answers hadn't shown up yet :P I will take one of them now lol. Also juanpa's comment hadn't loaded either, so I'd only seen the above ones – CapnShanty Jan 08 '19 at 20:36

4 Answers4

4

Use str.isdigit:

[tuple(int(y) if y.isdigit() else y for y in x) for x in tup]
# [(1001794, 'Us/Eastern', 2, 1, 3, 4, 5), ...]

This is assuming the numbers in your strings are integers. tup is your data structure.


To handle negative integers, use a function encapsulating a try-except block (read about the EAFP principle):

def try_convert(s):
    try:
        return int(s)
    except ValueError:
        return s

[tuple(try_convert(y) for y in x) for x in tup]
# [(1001794, 'Us/Eastern', 2, 1, 3, 4, 5), ...]    

To handle ints and floats, you may use a nested block:

def try_convert(s):
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            return s 
cs95
  • 379,657
  • 97
  • 704
  • 746
  • 2
    I like this answer. Thanks for pointing out the usefulness of `isdigit`. – joanis Jan 08 '19 at 20:42
  • 1
    Not a bad approach, provided all of the numbery-looking strings look like positive integers. "-2" will remain a string, for example. – Kevin Jan 08 '19 at 20:43
  • I'll give it to this one bc it's a good general solution in case anyone else has a similar problem – CapnShanty Jan 08 '19 at 20:43
  • I would say `isdigit` is not good here. Rather, encapsulate your `may_int` in a function, that uses `try: return int(obj) except ValueError: return obj`. Or just hard-code it. Tuples *should* be regular. – juanpa.arrivillaga Jan 08 '19 at 20:44
  • @Kevin Fixed, ty – cs95 Jan 08 '19 at 20:45
2

This worked for me:

y = [('1001794', 'Us/Eastern', '2', '1', '3', '4', '5'),
     ('1002041', 'Us/Eastern', '2', '4', '3', '5', '4')]
x = [(int(x[0]),x[1],int(x[2]),int(x[3]),int(x[4]),int(x[5]),int(x[6])) for x in y]
print(x)
[(1001794, 'Us/Eastern', 2, 1, 3, 4, 5), (1002041, 'Us/Eastern', 2, 4, 3, 5, 4)]

You just need the x = outside the [.

joanis
  • 10,635
  • 14
  • 30
  • 40
  • 1
    Yep, `tlist = [(int(x[0]),x[1],int(x[2]),int(x[3]),int(x[4]),int(x[5]),int(x[6])) for x in tlist]` works for me. – tgikal Jan 08 '19 at 20:33
  • 1
    This works but hardcodes everything, including the position of the string that should not be converted. – cs95 Jan 08 '19 at 20:37
1

If you know where the ints are, you can use Extended Iterable Unpacking to simplify the list comprehension you where trying to use:

[(int(x), y, *map(int,v)) for x, y, *v in l]

[(1001794, 'Us/Eastern', 2, 1, 3, 4, 5),
 (1001832, 'Us/Central', 2, 3, 4, 4, 5),
 (1001848, 'Us/Central', 2, 4, 5, 4, 5),
 (1001855, 'Us/Central', 2, 1, 4, 4, 5),
 (1001899, 'Us/Central', 2, 1, 4, 3, 5),
 (1001914, 'Us/Pacific', 1, 4, 2, 4, 5),
 (1001971, 'Us/Pacific', 3, 4, 2, 3, 5),
 (1002021, 'Us/Eastern', 2, 1, 4, 4, 5),
 (1002026, 'Us/Central', 2, 1, 4, 4, 2),
 (1002028, 'Us/Eastern', 2, 1, 4, 4, 5),
 (1002041, 'Us/Eastern', 2, 4, 3, 5, 4)]
yatu
  • 86,083
  • 12
  • 84
  • 139
0

is this the Answer your looking of ?

list = []
newList = []

list = [
        ('1001794', 'Us/Eastern', '2', '1', '3', '4', '5'),
        ('1001832', 'Us/Central', '2', '3', '4', '4', '5'),
        ('1001848', 'Us/Central', '2', '4', '5', '4', '5'),
        ('1001855', 'Us/Central', '2', '1', '4', '4', '5'),
        ('1001899', 'Us/Central', '2', '1', '4', '3', '5'),
        ('1001914', 'Us/Pacific', '1', '4', '2', '4', '5'),
        ('1001971', 'Us/Pacific', '3', '4', '2', '3', '5'),
        ('1002021', 'Us/Eastern', '2', '1', '4', '4', '5'),
        ('1002026', 'Us/Central', '2', '1', '4', '4', '2'),
        ('1002028', 'Us/Eastern', '2', '1', '4', '4', '5'),
        ('1002041', 'Us/Eastern', '2', '4', '3', '5', '4')
        ]

newList = [[int(x[0]), x[1], int(x[2]), int(x[3]), int(x[4]), int(x[5]), int(x[6])] for x in list]

print(newList)