1

Basically I have a string like this:

"1,2,3 2,3,4 3,4,5 4,5,6 5,6,7 26,117,1212" 

and I want to split it by spaces and then replace every i-th element in each element. So if I replace every 2nd element with 0, then the result will be:

"1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212" 

Should I just split it and then for each string element, split them inside a for loop, and then if I am at the specified index, then use the specified value, otherwise the element itself and then append this to the final string?

I thought there might be a much better/faster and shorter way to do the same thing in Python.

5 Answers 5

2
nums = [[int(num) for num in substring.split(',')] for substring in s.split()] for row in nums: row[1] = 0 

The first line converts the input out of text format and into a list of lists of numbers, and the second and third lines replace the second item in each sublist. At this point, if you need to print the numbers or write them to a file or something, you can convert back to a string, but if you need to keep doing things with the numbers, it's probably best to keep using the nums list.

If you're going to immediately turn the data back into a string, it's not worth calling int. In that case, the code reduces to

nums = [substring.split(',') for substring in s.split()] for row in nums: row[1] = '0' 

and then to convert back to a string,

string_representation = ' '.join(','.join(row) for row in nums) 

To replace the first or third element of every section, just replace the 1 in row[1] = '0' with the index you want to replace. 0 for the first element, 2 for the third. You can make a function taking the index you want to use:

def zero_out_column(s, index): nums = [substring.split(',') for substring in s.split()] for row in nums: row[index] = '0' return ' '.join(','.join(row) for row in nums) 
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks I will convert everything back to string because that's what the app uses.
@JoanVenge: Depending on what you mean by "that's what the app uses", it may be worthwhile to keep the nums list anyway.
Sorry I meant the app I am writing this script which will be invoked via a button, so I can't keep anything in memory after the code executed, and did its operation. But in the end I am just updating a parameter field in the program which in this case is a string, that's why I said that :)
2

Using numpy.matrix:

>>> import numpy as np >>> >>> s = "1,2,3 2,3,4 3,4,5 4,5,6 5,6,7 26,117,1212" >>> m = np.matrix(s.replace(' ', ';').replace(',', ' '), dtype=str) >>> m[:, 1] = '0' >>> ' '.join(map(','.join, np.asarray(m))) '1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212' 

Comments

2

Here is a regular expression version:

import re a = "1,2,3 2,3,4 3,4,5 4,5,6 5,6,7 26,117,1212" for i in range(3): print re.sub(r"((^| )(\d+,){%d})(\d+)" % i, r"\g<1>0", a) 

the output:

0,2,3 0,3,4 0,4,5 0,5,6 0,6,7 0,117,1212 1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212 1,2,0 2,3,0 3,4,0 4,5,0 5,6,0 26,117,0 

1 Comment

Very nice! Can you explain how the repl string r"\g<1>0" is resolved for given pattern?
1

I'm not sure what your ultimate goals are, but numpy excels at manipulating rectangles of numbers for fun and profit.

> import numpy as np; from StringIO import StringIO > s = "1,2,3 2,3,4 3,4,5 4,5,6 5,6,7 26,117,1212" > a = np.loadtxt(StringIO(s.replace(' ', '\n')), delimiter=',', dtype=int) > a # ah, much better array([[ 1, 2, 3], [ 2, 3, 4], [ 3, 4, 5], [ 4, 5, 6], [ 5, 6, 7], [ 26, 117, 1212]]) > a[:, 1] = 0 # all the rows, column 1 > a array([[ 1, 0, 3], [ 2, 0, 4], [ 3, 0, 5], [ 4, 0, 6], [ 5, 0, 7], [ 26, 0, 1212]]) > (' '.join(['%s,%s,%s'] * len(a))) % tuple(a.flatten()) # okay, apply silly formatting '1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212' 

2 Comments

Rather than eval, it's probably better to use numpy.loadtxt with a StringIO object.
Pretty numpy wizardry :)
1

@Joan, your approach seems about right. You can do as you suggest all at once, using list comprehension:

>>> s = "1,2,3 2,3,4 3,4,5 4,5,6 5,6,7 26,117,1212" >>> ' '.join([','.join([[n,'0'][int(i==1)] for i,n in enumerate(e.split(','))]) ... for e in s.split(' ')]) 1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212 

Or, for a running i:

>>> print('\n'.join([' '.join([','.join([[n,'0'][int(i==j)] for j,n in enumerate(e.split(','))]) for e in s.split(' ')]) for i in range(3)])) 0,2,3 0,3,4 0,4,5 0,5,6 0,6,7 0,117,1212 1,0,3 2,0,4 3,0,5 4,0,6 5,0,7 26,0,1212 1,2,0 2,3,0 3,4,0 4,5,0 5,6,0 26,117,0 

In any case, s is split at spaces ('') first, each resulting fragment is itself split at commas (,), so that we can loop over the fragment's single elements, alongside a running integer [as returned by enumerate(seq)], with which we test each element for being the ith item of its fragment, in which case we overwrite it with a 0. The nested lists we got by doing all this are then reassembled bottom-up into the original input string format by reinserting the respective separator characters, using the join([...]) function.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.