简体   繁体   中英

Python slicing list of tuples and converting values to integers - Confusion regarding why it's possible with numpy arrays but not list of tuples

I am trying to slice the first and last values from a list of list then convert these values to integers. I found a solution but I am confused why this solution works and am wondering if there is a simpler way as it seems rather inelegant.

The two ways I found to slice a single value from a list of a list are either to use list comprehension and then slice or convert to a numpy array then slice in two dimensions. Both of these take two steps.

Question 1 : is there a single step solution to slice a single value out of a list of a list?
Question 2 : Why is a mixed list (some values being numbers and some letters) not made up of integers and strings vs all tuples? Do numpy arrays or another approach allow mixed lists? Sorry if I am not using the correct terminology...

List of a list slicing - list comprehension method

#Say I have a list of a list with mixed numbers and letters.

>>>a=[('1', 'T', ''), ('2', 'R', 'S'), ('3', 'E', 'S'), ('4', 'T', 'S')]
#list comprehension slice 1D
>>>b=[list[0:1] for list in a]
>>> print(b):
[('1',), ('2',), ('3',), ('4',)]

>>> start=(b[0:1])
>>> print(start):
[('1',)]
>>> end=b[len(b)-1:len(b)]
>>> print(end)
[('4',)]

List of a list slicing - numpy array method #Say I have a list of a list with mixed numbers and letters.

>>>a=[('1', 'T', ''), ('2', 'R', 'S'), ('3', 'E', 'S'), ('4', 'T', 'S')]
>>> b_array=numpy.array(a)
>>> print(b_array)
array([['1', 'T', ''],
       ['2', 'R', 'S'],
       ['3', 'E', 'S'],
       ['4', 'T', 'S']], dtype='<U1')

>>>start_array = b_array[0:1,0:1]
>>>print(start_array)
array([['1']], dtype='<U1')

>>>end_array = b_array[len(b_array)-1:len(b_array),0:1]
>>>print(end_array)
array([['4']], dtype='<U1')

Both approaches work but what confuses me is they behave differently if I call int() on them List comprehension If I either use list comprehension to try to turn all of b into integers

>>>b_int= [int(i) for i in b] 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple'

or turn start or end into integers

>>>start=int(b[0:1])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

I get thrown similar errors. But the second says it is a list even though it's a single value in a 1x1 list.

Alternatively if I do the same for start_array it's fine

>>>start_array=int(b_array[0:1,0:1])
>>>print(start_array)
1

So in summary, I figured out a working solution but it feels clunky and I don't understand why this works in numpy arrays but not list of lists.

Question 3 : Why can I convert values in numpy arrays into integers not list of lists?
Question 4 : Is there a cleaner or easier way to do this in python?

Thanks

edit: So my misunderstanding was that I thought I was dealing with a list of lists. I was not, instead I was working with a list of tuples. I changed the title but not the body. My second problem was I was slice indexing and not scalar indexing. This resulted in not removing my elements from the list. For solutions I could either:

#List comprehension to reduce dimensionality
a=[('1', 'T', ''), ('2', 'R', 'S'), ('3', 'E', 'S'), ('4', 'T','S')]
b=[x[0] for x in a]
start=int(b[0])
end=int(b[-1])

#Directly index with a scalar
start=int(b[0][0])
end=int(b[-1][0])

I will directly index with a scalar as it's simpler. Though if I wanted to index several numbers list comprehension would be more useful.

If you just want the first and last number to be converted to integer, you can simply do this:

a = [('1', 'T', ''), ('2', 'R', 'S'), ('3', 'E', 'S'), ('4', 'T', 'S')]

firstNum = int(a[0][0])
lastNum = int(a[-1][0])

print(firstNum)
print(lastNum)

There is no need for slicing or other complicated logic. And you are getting error because you cannot convert a tuple into integer, select the item inside tuple and then convert it

You are indexing with slices, which returns a list (or tuple). Indexing with a number (scalar) takes an element out of the list (or tuple):

In [8]: a=[('1', 'T', ''), ('2', 'R', 'S'), ('3', 'E', 'S'), ('4', 'T', 'S')]                  
In [9]: b=[x[0] for x in a]                                                                    
In [10]: b                                                                                     
Out[10]: ['1', '2', '3', '4']
In [11]: b[0]                                                                                  
Out[11]: '1'
In [12]: int(b[0])                                                                             
Out[12]: 1
In [13]: b[-1]                                                                                 
Out[13]: '4'    # int(b[-1]) works

Similarly with an array. Slice index retains the dimension, scalar index reduces the dimension(s):

In [14]: arr = np.array(a)                                                                     
In [15]: arr                                                                                   
Out[15]: 
array([['1', 'T', ''],
       ['2', 'R', 'S'],
       ['3', 'E', 'S'],
       ['4', 'T', 'S']], dtype='<U1')
In [16]: arr[0,:]                                                                              
Out[16]: array(['1', 'T', ''], dtype='<U1')
In [17]: arr[:,0]                                                                              
Out[17]: array(['1', '2', '3', '4'], dtype='<U1')

Note the arr dtype; we can change that to int :

In [18]: arr[:,0].astype(int)                                                                  
Out[18]: array([1, 2, 3, 4])

In general you don't want to use int(b_array[0:1,0:1]) . It works for one number, but not several:

In [19]: int(arr[:,0])                                                                         
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-9c2041fff718> in <module>
----> 1 int(arr[:,0])

TypeError: only size-1 arrays can be converted to Python scalars

The list indexing is the Python original. numpy has extended this indexing. numpy extensions have not been back-ported to list .


Something you may have missed is that iterating on a list takes items out of the list.

In [26]: [x for x in a[:2]]                                                                    
Out[26]: [('1', 'T', ''), ('2', 'R', 'S')]

is equivalent to indexing with a scalar:

In [27]: [a[i] for i in range(2)]                                                              
Out[27]: [('1', 'T', ''), ('2', 'R', 'S')]

Indexing with slice 'wraps' each x in a list:

In [28]: [a[i:i+1] for i in range(2)]                                                          
Out[28]: [[('1', 'T', '')], [('2', 'R', 'S')]]

In b=[list[0:1] for list in a] , list is one of the tuples in a . It is not a slice of a .

In [29]: a[0][0:1]         # slice of a tuple from a list                                                                             
Out[29]: ('1',)
In [30]: a[0:1][0:1]       # slice of a slice                                      
Out[30]: [('1', 'T', '')]
In [31]: a[0][0]           # element of a tuple from the list                                                  
Out[31]: '1'

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