striplines() not working when using finditer python - python

I am trying to convert a multiline string to a single list which should be possible using splitlines() but for some reason it continues to convert each line into a list instead of processing all the lines at once. I tried to do it out of the for loop but doesnt seem to have any effect. I need the lines as a single list to use it another function. Below is how I get the multiline into a single variable. What am I missing???
multiline_string_final = []
for match_multiline in re.finditer(r'(^(\w+):\sThis particular string\s*|This particular string\s*)\{\s(\w+)\s\{(.*?)\}', string, re.DOTALL):
multi_line_string = match_multiline.group(4)
print multiline_string
This last print statement prints out the strings like this:
blah=0; blah_blah=1; Foo=3;
blah=4; blah_blah=5; Foo=0;
However I need:
['blah=0; blah_blah=1; Foo=3;''blah=4; blah_blah=5; Foo=0;']
I understand it has to be something with the finditer but cant seem to rectify.

Your new problem also has nothing to do with finditer. (Also, your code is still not an MCVE, you still haven't shown us the sample input data, etc., making it harder to help you.)
From this desired output:
['blah=0; blah_blah=1; Foo=3;''blah=4; blah_blah=5; Foo=0;']
I'm pretty sure what you're looking for is to get a list of the matches, instead of printing out each match on its own. That isn't a valid list, because it's missing the comma between the elements,* but I'll assume that's a typo from you making up data instead of building an MCVE and copying and pasting the real output.
Anyway, to get a list, you have to build a list. Printing things to the screen doesn't build anything. So, try this:
multiline_string_final.append(multiline_string)
Then, at the end—not inside the loop, only after the loop has finished—you can print that out:
print multiline_string_final
And it'll look like this:
['blah=0; blah_blah=1; Foo=3;',
'blah=4; blah_blah=5; Foo=0;']
* Actually, it is a valid list, because adjacent strings get concatenated… but it's not the string you wanted, and not a format Python would ever print out for you.

The problem has nothing to do with the finditer, it's that you're doing the wrong thing:
for line in multiline_string:
print multiline_string.splitlines()
If multiline_string really is a multiline string, then for line in multiline_string will iterate over the characters of that string.
Then, within the loop, you completely ignore line anyway, and instead print multiline_string.splitlines()).
So, if multiline_string is this:
abc
def
Then you'll print ['abc\n', 'def\n'] 8 times in a row. That's not what you want (or what you described).
What you want to do is:
split the string into lines
loop over those lines, not over the original un-split string
print each line, not the whole thing
So:
for line in multiline_string.splitlines():
print line

Related

Trying to replace \t with \s with regex in Python, but as a result "Unhashable type:list" error

I am new to programming and have already checked other people's questions to make sure that I am using a good method to replace tabs with spaces, know my regex is correct, and also understand what exactly my error is ("Unhashable type 'list'). But even still, I'm at a loss of what to do. Any help would be great!
I have a large file that I have broken up into lines. Ultimately I will need to access the first 3 elements of each line. Currently when I print a line, without the additional re.sub line of code, I get something like this: ['blah\tblah\tblah'], when I want ['blah blah blah'].
My code to do this is
f = open(text.txt)
raw = f.read()
raw = raw.lower()
lines = raw.splitlines()
lines = re.sub(r'\t', lines, '\s')
print lines[0:2] #just to see the first few examples
f.close()
When I print the first few lines without the regex sub bit, it works fine. And then when I add that line in attempt to change the lines, I get the error. I understand that lists are changeable and thus can't be a hashed... but I'm not trying to work with a hash. I'm just trying to replace \t with \s in a large text file to make the program easier to work with. I don't think there is a problem with how I am changing \t's to \s's, because according to this error, any way I change it will break my code. What do I do?! Any help is super appreciated. :')
You need to change the order of params present inside the re.sub function. And also note that you can't use regex \s as a second param in re.sub function. Syntax of re.sub must be re.sub(regex,replacement,string) .
lines = raw.splitlines()
lines = [re.sub(r'\t', ' ', line) for line in lines]
raw.splitlines() returns a list which was then assigned to a variable called lines. So you need to apply the re.sub function to each item present in the list, since re.sub won't directly be applied on a list.

Python variables stored in text files not working, but should be

I've settled on a text-file based save system for my game, storing the values of required variables with keywords - for example, the password that tells the game which chapter to play. However, it appears to be malfunctioning, and I can't see why.
Before starting the game, we have:
if not os.file.isfile('TSGsave{0}.txt'.format(name)):
TSGsave=open('TSGsave{0}.txt'.format(name),'wt')
TSGsave.write('\nw5CT$n<jfW=-#J%4Ya5##')
TSGsave.close()
(the keyword used is a bunch of jibberish so that the user can't change it knowing what's going to happen). This adds w5CT$n<jfW=-#J%4Ya5## to the text file. We then have:
for i in range (len(lines)):
if 'w5CT$n<jfW' in lines[i]:
findpass=lines[i]
for i in range (len(findpass)):
if findpass[i]=='=':
cutfrom=i+1
password=findpass[cutfrom:len(findpass)]
to retrieve the variable (which can change, so it can't be written in as definite value). I know it works, because I added print (password) to the code and it returned -#J%4Ya5##. Then to start the corresponding chapter, the code is:
if password=='-#J%4Ya5##':
but it isn't starting the indented block. In the shell, the program ends and goes back to the >>> line.
If there is a way to fix this code, great - but another code to do the same thing would work just as well.
Your lines contain newlines, and these are being included. Strip these from the line:
findpass = lines[i].rstrip('\n')
Printing a value with a newline in it will simply add an extra black line after the print. Always use the repr() function to produce a Python representation of strings to see such characters:
>>> print '-#J%4Ya5##\n'
-#J%4Ya5##
>>> print repr('-#J%4Ya5##\n')
'-#J%4Ya5##\n'
Your parsing code is overly complicated; you can use str.split() or str.partition() to split your password from the line instead. You should just loop over the lines list directly rather than produce indices with range():
for line in lines:
if 'w5CT$n<jfW' in line:
password = line.partition('=')[2].rstrip('\n')

Remove duplicates from a list in Python

I have a python script which parses an xml file and then gives me the required information. My output looks like this, and is 100% correct:
output = ['77:275,77:424,77:425,77:426,77:427,77:412,77:413,77:414,77:412,77:413,77:414,77:412,77:413,77:414,77:412,77:413,77:414,77:431,77:432,77:433,77:435,77:467,77:470,77:471,77:484,77:485,77:475,77:476,77:437,77:438,77:439,77:440,77:442,77:443,77:444,77:445,77:446,77:447,77:449,77:450,77:451,77:454,77:455,77:456,77:305,77:309,77:496,77:497,77:500,77:504,77:506,77:507,77:508,77:513,77:515,77:514,77:517,77:518,77:519,77:521,77:522,77:523,77:403,77:406,77:404,77:405,77:403,77:406,77:404,77:405,77:526,77:496,77:497,77:500,77:504,77:506,77:507,77:508,77:513,77:515,77:514,77:517,77:518,77:519,77:521,77:522,77:523,77:403,77:406,77:404,77:405,77:403,77:406,77:404,77:405,77:526,77:317,77:321,77:346,77:349,77:350,77:351,77:496,77:497,77:500,77:504,77:506,77:507,77:508,77:513,77:515,77:514,77:517,77:518,77:519,77:521,77:522,77:523,77:403,77:406,77:404,77:405,77:403,77:406,77:404,77:405,77:526,77:496,77:497,77:500,77:504,77:506,77:507,77:508,77:513,77:515,77:514,77:517,77:518,77:519,77:521,77:522,77:523,77:403,77:406,77:404,77:405,77:403,77:406,77:404,77:405,77:526,77:362,77:367,77:369,77:374,77:370,77:372,77:373,77:387,77:388,77:389,77:392,77:393,77:394,77:328,77:283,77:284,77:285,77:288,77:289,77:290,77:292,']
It is all fine, but I want to remove the duplicate elements in an element, like in the case above. I tried using the OrderedDict package or just simple list(set(output)), but obvoiusly they both didn't work. Does anyone have a tip for me on how to solve this problem.
You have one element in a list. If you expected it to be treated as separate elements, you need to explicitly split it.
You could split the string on the ',' comma character into a list with str.split():
separate_elements = output[0].split(',')
after which you can use set() (unordered) or OrderedDict (maintaining order) and re-join the string if you still need just the one string object:
','.join(set(separate_elements))
You can put that back into a list with just one element, but there is little point if all you ever handle is that one string.

Python - print a list adding empty lines at determined points

I have a list that contains logs, and I am trying to add an empty line between specific blocks. So when I get to the end of a specific block, I can see a bit of separation, instead of looking like a continuous list.
EX:
log a:
kdsaldklsadkaslk
kasldkasldkasldkasldk
log a1:
lkpadkfaldkfdsl
klsdkfldskfsdl
So far I've tried all that I was able to find online, but I was unsuccessful. Either I am forced to add anything but an empty line (like a sequence of ----- for example), or the space added will be added to every single line (which is not what I want).
If I add in the list the empty line, like
log_list.append(" \n")
when I print the list using
print "\n".join(log_list)
all the empty lines that I have added are not printed.
But if I add any character to the append command, then it will be printed.
Is there any option that is automatically taking off the empty lines in a list, when I do the join command? Otherwise I do not understand why I cannot have an empty line in the list.
Is there another way to print out lists? I've always seen printing lists with the join command (all my objects in the list are strings).
Thanks!
For me, this works (showing that there is no monkey business with appending a \n and then joining with a \n):
>>> log_list = ['a']
>>> log_list.append('\n')
>>> log_list.append('b')
>>> log_list.append('c')
>>> print '\n'.join(log_list)
a
b
c
What did you do differently?
If the list is already created, you can for example insert a blank line before every line ending with ":" like this
print "\n".join("\n"+s if s.endswith(":") else s for s in log_list)
It's probably clearer to just use a loop though
for s in log_list:
if s.endswith(":"):
print
print s
You can change the condition to suit your requirements, eg s.startswith("log ")

python print string on multiple lines

I have a function that can only accept strings. (it creates the image with the string, but the string has little formatting and no word wrapping, so a long string will just bleed right through the edge of the image and keep going into the abyss, when in reality I would have liked it to create a paragraph, instead of a one line infinity).
I need it print with line breaks. Currently the file is being readin using
inputFiles.readlines()
so that this reads the entire file. Storing file.readLines() creates a list. So this list cannot be passed to my function looking for a string.
I used
inputFileContent = ' \n'.join(inputFiles.readLines())
in an attempt to force hard line breaks into the string between each list item. This does not work (edit: elaboration here) which means that the inputFileContent string does not have line breaks even though I put '\n' between the list elements. From my understanding, the readLines() function puts the individual lines into individual elements of a list.
any suggestions? Thank you
Use inputFiles.read() which creates a string. Does that help?
The 'join' should have worked. Your problem may be that the writing of the string ignores newline characters. You could maybe try '\r\n'.join(...)

Categories