0

I'm reading files from a text file called WeaponShack.list

These are the contents of 'weapon shack.list':

Grenade
Ak-47
Shotgun
Makarov
Minigun
Bat
Katana
Chainsaw
Flamethrower

There are no whitespaces. These items are copy-pasted as is.

I try to strip down some newline characters but the "\n" character just keeps showing up at some elements when I print the list. I don't understand why.

I tried using .strip('\n') but the "\n" characters still pop up at the end of some elements.

print("Taking weapons from Weapon shack")
weapons = []
with open("WeaponShack.list",'r') as ws:
    weapons = ws.readlines()
    for weapon in weapons:
        weapons.remove(weapon)
        weapon = weapon.strip('\n')
        weapons.append(weapon)
ws.close()
print(weapons)

The expected output is:

Taking weapons from Weapon shack ['Ak-47', 'Makarov', 'Bat', 'Chainsaw', 'Grenade', 'Minigun', 'Flamethrower', 'Katana', 'Shotgun']

But the actual output is:

Taking weapons from Weapon shack ['Ak-47\n', 'Makarov\n', 'Bat\n', 'Chainsaw\n', 'Grenade', 'Minigun', 'Flamethrower', 'Katana', 'Shotgun']

Does anyone know why this is happening?

EDIT My focus is why the "\n" character appears. Not how to traverse lists. Also trying the suggestion: adding a new list:

print("Taking weapons from Weapon shack")
weapons = []
newWeaponList = []
with open("WeaponShack.list",'r') as ws:
    weapons = ws.readlines()
    for weapon in weapons:
        weapons.remove(weapon)
        weapon = weapon.strip('\n')
        newWeaponList.append(weapon)
ws.close()
print(newWeaponList)

produces this output:

Taking weapons from Weapon shack ['Grenade', 'Shotgun', 'Minigun', 'Katana', 'Flamethrower']

Weird because it doesn't show all the elements.

  • 1
    Because you're modifying the list while iterating over it. Create a new list instead. – rdas May 31 '19 at 16:42
  • Possible duplicate of [Modifying a list while traversing it](https://stackoverflow.com/questions/26899872/modifying-a-list-while-traversing-it) – rdas May 31 '19 at 16:42
  • Does doing that cause the "\n" character to appear? And if yes? Why so? – Jan Daenell Bancud May 31 '19 at 16:45
  • Removing things from a list while iterating over it messes with the relative order of the elements in the list. Since you only iterate over the list once, some elements might get skipped. So the `\n` is not appearing - it's just never removed from some of the elements. – rdas May 31 '19 at 16:47
  • Possible duplicate of [How to modify list entries during for loop?](https://stackoverflow.com/questions/4081217/how-to-modify-list-entries-during-for-loop) – Thierry Lathuille May 31 '19 at 16:49

2 Answers2

2

It is because you are both reading and modifying the list preventing traversal of each element. The weapons with '\n' at the end are never reached by weapon.strip('\n')

To make it cleaner remove the traversal problem and get rid of the new spaces, try something like this answer:

print("Taking weapons from Weapon shack")
with open("weapons.list") as ws:
    readWeapons = ws.readlines()
    for weapon in readWeapons:
        weapon = weapon.rstrip('\n')
        weapons.append(weapon)
print(weapons)

Edit:

To answer your clarification, it's because of how the for loop in python works. I am not privy to the exact details, but it appears that the for loop actually accesses the array in real time rather than read the entire array at once. Check out this reading from test.list which contains four lines corresponding to A-D:

print("Taking item from test\n")
with open("test.list",'r') as ws:
    elements = ws.readlines()
    print(elements)
    print()
    for element in elements:
        print('Current element: ' + element)
        elements.remove(element)
        print('Element pre-strip: ' + str(elements))
        element = element.strip('\n')
        print('Stripped element: ' + element)
        elements.append(element)
        print('Element list post-strip: ' + str(elements))

Output:

Taking item from test

['A\n', 'B\n', 'C\n', 'D\n']

Current element: A

Element pre-strip: ['B\n', 'C\n', 'D\n']
Stripped element: A
Element list post-strip: ['B\n', 'C\n', 'D\n', 'A']
Current element: C

Element pre-strip: ['B\n', 'D\n', 'A']
Stripped element: C
Element list post-strip: ['B\n', 'D\n', 'A', 'C']
Current element: A
Element pre-strip: ['B\n', 'D\n', 'C']
Stripped element: A
Element list post-strip: ['B\n', 'D\n', 'C', 'A']
Current element: A
Element pre-strip: ['B\n', 'D\n', 'C']
Stripped element: A
Element list post-strip: ['B\n', 'D\n', 'C', 'A']

Because of of the appending rather than prepending, every other element is being skipped as the for loop moves from index a of the array to index a + 1 of the array. This causes, B and D (indices 1 and 3) to be skipped and A to be read 3 times.

Jack Thomson
  • 450
  • 4
  • 9
1

@rdas Thank you for your help.

" Removing things from a list while iterating over it messes with the relative order of the elements in the list. Since you only iterate over the list once, some elements might get skipped. So the \n is not appearing - it's just never removed from some of the elements."

I removed the weapons.remove(weapon) line and it fixed it!

Cheers!