Splitting strings within nested lists [duplicate] - python

This question already has answers here:
Python Variable assignment in a for loop
(6 answers)
Closed 1 year ago.
I am trying to split strings within nested lists, but for whatever reason, the strings do not split as I expect them to. For example, here is a nested list where I have strings that I want to split.
myList=[['letters', ['a b c d e', 'f g h i j']], ['digits', ['0 1 2 3 4', '5 6 7 8 9']]]
I have tried using for loops to split each string, but it doesn't seem to work. I tried using the following code:
for i in myList:
for j in i[1]:
j=j.split()
However, it seems to do nothing to the list. I expect that after running the code, myList should contain
[['letters', [['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j']]], ['digits', [['0', '1', '2', '3', '4'], ['5', '6', '7', '8', '9']]]]
If I look at each item using print() and repr(), I see the strings that I expect.
for i in myList2:
for j in i[1]:
print(repr(j))
prints out
'a b c d e'
'f g h i j'
'0 1 2 3 4'
'5 6 7 8 9'
as I expect, so I am unsure why the split values cannot be written.

The syntax j = j.split() doesn't modify the object referenced by j, it just reference j to a NEW thing : the splitted list, and that have no impact on the main list, you need to create a new one
myList = [[i[0], [j.split() for j in i[1]]] for i in myList]
Heavier, but maybe more understandable syntax
result = []
for i in myList:
tmp_list = []
for j in i[1]:
tmp_list.append(j.split())
result.append([i[0], tmp_list])
print(result)

You should specify the location in the nested list to overwrite. Modifying your code as follows:
for idx, i in enumerate(myList):
for ix, j in enumerate(i[1]):
# j = j.split()
myList[idx][1][ix] = j.split()
print(myList)
results in required output.

Related

Python: split one element in list [duplicate]

This question already has answers here:
How do I split a string into a list of characters?
(15 answers)
Changing one element in a list from string to integer
(1 answer)
Closed 1 year ago.
Can not solve problem i have following list ['882','200','60'] sometimes it can be ['882','200'] i want get list like this [['8','8','2'], '200', '60'].
Another words no matter how many items are in the list, we always split the first item
You can use enumerate to get the first element:
l = ['882','200','60']
[e if i else list(e) for i,e in enumerate(l)]
output:
[['8', '8', '2'], '200', '60']
other examples
>>> [e if i else list(e) for i,e in enumerate(['123'])]
[['1', '2', '3']]
>>> [e if i else list(e) for i,e in enumerate(['882','200'])]
[['8', '8', '2'], '200']
mylist = ['882','200','60']
mylist[0] = list(mylist[0])

Code works only sometimes for removing odd or even index items

Question :​ Write a Python program to remove the characters which have odd or even index
values of a given string.
I tried to make a copy of the list by deep copy .
I ran a loop from first list and checked for even then used pop method on second list to remove that specific index from the second list .
This code works for some inputs , I think mostly for those which doesn't have any repeated characters and doesn't work for others.
Code
#!/usr/bin/python3
import copy
list1 = input("Enter a string ")
list1 = list(list1)
list2 = copy.deepcopy(list1)
for i in list1:
if list1.index(i)%2 != 0:
list2.pop(list2.index(i))
print(list2)
The outputs for some samples are :
123456789 -> ['1', '3', '5', '7', '9'], qwertyuiop -> ['q', 'e', 't', 'u', 'o'], saurav -> ['s', 'u'], 11112222333344445555 -> ['1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4', '4', '4', '4', '5', '5', '5', '5']
Read the documentation for index. It returns the index of the first occurrence of the given value. A simple print inside the loop will show you what's going on, in appropriate detail. This is a basic debugging skill you need to learn for programming in any language.
import copy
list1 = input("Enter a string ")
list1 = list(list1)
list2 = copy.deepcopy(list1)
for i in list1:
if list1.index(i)%2 != 0:
print(i, list1.index(i), list2.index(i))
list2.pop(list2.index(i))
print(list2)
print(list2)
output:
Enter a string google
o 1 1
['g', 'o', 'g', 'l', 'e']
o 1 1
['g', 'g', 'l', 'e']
e 5 3
['g', 'g', 'l']
['g', 'g', 'l']
... and that's your trouble. Fix your logic. You already know the needed index to save or remove. There is no need to extract the character, and then search for it again. You already know where it is.
Even better, simply slice the original string for the characters you want:
print(list1[::2])
Your problem is the list.index function. The documentation states that it "returns zero-based index in the list of the first item whose value is equal to x." Because you are calling it on list1 - and that is not modified - the result will always be list1.index('a') == 1 for example.
The correct solution would be to use enumerate. A further problem exists here - because you are indexing from an array that you have not modified, you indexes will be off after the first list.pop operation. Every item after the one removed will have been shifted by 1. To correct this, you could instead try building a list instead of emptying one:
#!/usr/bin/python3
list1 = input("Enter a string ")
list2 = []
for i, item in enumerate(list1):
if i % 2 == 0:
list2.append(item)
print(list2)
You don't need to iterate at all. Just reference the string elements directly.
st="123456789"
print('Odd: ', list(st[::2]))
print('Even: ', list(st[1::2]))
Output:
Odd: ['1', '3', '5', '7', '9']
Even: ['2', '4', '6', '8']
The method list.index(i) returns index in the list of the first item whose value is equal to i.
For example, "saurav".index('a') returns 1. when you call list2.pop(list2.index(i)) and you want to pop an a, it doesn't work well.
I think it can be simple using range as build-in function.
list1 = list(input("Enter a string "))
list2 = list()
for i in range(len(list1)):
if i % 2 == 0:
list2.append(list1[i])
print(list2)
It works with same way by following:
list1 = list(input("Enter a string "))
list2 = list()
for i in range(0, len(list1), 2):
list2.append(list1[i])
print(list2)
Also, you can use Extended Slices in Python 2.3 or above.
list1 = list(input("Enter a string "))
list2 = list1[::2]
print(list2)

Print 2 lists side by side

I'm trying to output the values of 2 lists side by side using list comprehension. I have an example below that shows what I'm trying to accomplish. Is this possible?
code:
#example lists, the real lists will either have less or more values
a = ['a', 'b', 'c,']
b = ['1', '0', '0']
str = ('``` \n'
'results: \n\n'
'options votes \n'
#this line is the part I need help with: list comprehension for the 2 lists to output the values as shown below
'```')
print(str)
#what I want it to look like:
'''
results:
options votes
a 1
b 0
c 0
'''
You can use the zip() function to join lists together.
a = ['a', 'b', 'c']
b = ['1', '0', '0']
res = "\n".join("{} {}".format(x, y) for x, y in zip(a, b))
The zip() function will iterate tuples with the corresponding elements from each of the lists, which you can then format as Michael Butscher suggested in the comments.
Finally, just join() them together with newlines and you have the string you want.
print(res)
a 1
b 0
c 0
This works:
a = ['a', 'b', 'c']
b = ['1', '0', '0']
print("options votes")
for i in range(len(a)):
print(a[i] + '\t ' + b[i])
Outputs:
options votes
a 1
b 0
c 0
from __future__ import print_function # if using Python 2
a = ['a', 'b', 'c']
b = ['1', '0', '0']
print("""results:
options\tvotes""")
for x, y in zip(a, b):
print(x, y, sep='\t\t')
[print(x,y) for x,y in zip(list1, list2)]
Note the square brackets enclosing the print statement.

Comparing elements between two lists of lists in python

List A:
[('Harry', 'X', 'A'),
('James', 'Y', 'G'),
('John', 'Z', 'D')]
List B:
[('Helen', '2', '(A; B)', '3'),
('Victor', '9', '(C; D; E)', '4'),
('Alan', '10', '(A)', '57'),
('Paul', '11', '(F; B)', '43'),
('Sandra', '12', '(F)', '31')]
Basically I have to compare the third element (for x in listA -> x[2]) from list A and check if is there any list in list B that has the same element (for y in listB, x[2] == y[2]) but I'm just losing my mind with this.
My idea was to get the third element from each list in list B, put them into a new list, and then remove that ";" so I could access each element way more easily.
for x in listB:
j = x[2]
j = j.strip().split(', ')
for k in j:
FinalB.append(k)
FinalB = [(k[1:-1].split(";")) for k in FinalB]
Then I'd take the third element from each list of list A and compare them with the elements inside each list of FinalB: if there was a match, I'd get the index of the element in FinalB (the one that's matched), use that index to access his list in listB and get the first element of his list inside list B (basically, I have to know the names from the users inside each list that have the same 3rd element)
My code so far:
FinalB= []
DomainsList = []
for x in listA:
j = x[2]
j = j.strip().split(', ')
for k in j:
FinalB.append(k)
FinalB = [(k[1:-1].split(";")) for k in FinalB]
for y in listA:
for z in FinalB:
for k in z:
if y[2] == k:
m = FinalB.index(z)
DomainsList.append([listA[m][0],listB[m][0]])
return DomainsList
Yes, this is not working (no error, I probably just did this in an absolute wrong way) and I can't figure out what and where I'm doing wrong.
First, I think a better way to handle '(C; D; E)' is to change it to 'CDE', so the first loop becomes:
FinalB = [filter(str.isalpha, x[2]) for x in listB]
We take each string and keep only the alpha characters, so we end up with:
In [18]: FinalB
Out[18]: ['AB', 'CDE', 'A', 'FB', 'F']
This means we can use listA[x][2] in FinalB[y] to test if we have a match:
for y in listA:
for z in FinalB:
if y[2] in z:
DomainsList.append([y[0], listB[FinalB.index(z)][0]])
I had to tweak the arguments to the append() to pick the right elements, so we end up with:
In [17]: DomainsList
Out[17]: [['Harry', 'Helen'], ['Harry', 'Alan'], ['John', 'Victor']]
Usefully, if instead of '(C; D; E)' you have '(foo; bar; baz)', then with just one tweak the code can work for that too:
import re
FinalB = [filter(None, re.split("[; \(\)]+", x[2])) for x in listB]
The remaining code works as before.
It will always help to start a question with context and details.
The python version could also come into play.
The data structure you have given for us to work with is very questionable - especially the third element in each of the tuples in listB...why have a string element and then define it like this '(C; D; E)' ??
Even though I don't understand where you are coming from with this or what this is meant to achieve,no context provided in post, this code should get you there.
It will give you a list of tupples ( listC ), with each tuple having two elements. Element one having the name from listA and element 2 having the name from listB where they have a match as described in post.
NOTE: at the moment the match is simply done with a find, which will work perfectly with the provided details, however you may need to change this to be suitable for your needs if you could have data that would cause false positives or if you want to ignore case.
listA = [('Harry', 'X', 'A'), ('James', 'Y', 'G'), ('John', 'Z', 'D')]
listB = [('Helen', '2', '(A; B)', '3'),
('Victor', '9', '(C; D; E)', '4'),
('Alan', '10', '(A)', '57'),
('Paul', '11', '(F; B)', '43'),
('Sandra', '12', '(F)', '31')]
listC = []
for a in listA:
for b in listB:
if b[2].find(a[2]) != -1:
listC.append((a[0], b[0]))
print(listC)
This gives you.
[('Harry', 'Helen'), ('Harry', 'Alan'), ('John', 'Victor')]

Looping through a list of strings in Python sometimes only sees last element of list

(ep is a list of strings with a len of 58.)
Calling list on a string is supposed to give a list of the characters. But why in this case did it only see the last string? (Note, unlike this question, each element is unique).
for s in ep:
ll = list(s)
ll
['3', '5', '0', ' ', 'U', '.', 'S', '.', ' ', '1', '0', '1', '0']`
While in this loop with print() it sees all the elements, but doesn't modify any:
for s in ep:
ll = list(s)
print(s)
350 U.S. 1
350 U.S. 3
Here's another for loop with print that works:
for e in ep:
print([e])
['350 U.S. 1']
['350 U.S. 3']
And another without it that only sees the last element:
for e in ep:
ep5 = [e.strip("'").replace(' ', ",")]
ep5
['350,U.S.,1010']
And finally:
for e in ep:
ep11 = e.split()
print(ep11)
['350', 'U.S.', '1']
['350', 'U.S.', '3']
...<snip>...
['350', 'U.S.', '1010']
BUT....
ep11
['350', 'U.S.', '1010']
Both a list comprehension and enumerate (omitted) see all the elements, but not the simple for loop, at least not without print(). I know print() adds a newline, but I can't see how that alone accounts for this behavior. Can anyone explain this to me? Python 3.5.2 on Ubuntu 16.04. Thanks.
You're overwriting the same ll variable over and over again. Only the last value written will remain.
If you expect the result to be a list of list of string variables, then create a new list and add to it on every iteration:
characterLists = []
for s in strings:
characterLists.append(list(s))
print(characterLists)
Better yet, just use a list comprehension:
characterLists = [list(s) for s in strings]
print(characterLists)

Categories

Resources