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.