How to hide part of string in python - python

I am just wondering if there is such possibility to hide somehow part of string in python. I am not talking about slicing. I am talking about situation where I have "1somestring," while printing I obtain "somestring". 1 before somestring should be visible for python but not displayable. Or It could be nice to have some kind of indicator glued to string. What I want to achieve is custom sorting. I have list of strings and I want to sort them by addition of digits in front of them. Sorting will proceed basing on digits thus behind digits I can insert whatever I want, but I don’t want to have digits visible. Thanks for answers in advance.

You could store them in a list, with each entry consisting of a tuple indicating order (low to high), then the string. The default sorting on this list would place them in order.
words = [(1,"blah"), (3,"wibble"), (2,"splop")]
words.sort()
print(words)
[(1, 'blah'), (2, 'splop'), (3, 'wibble')]
print(" ".join(word[1] for word in words))
blah splop wibble

I think something simple like a situation where you have a list of things like:
['1something', '2more', '3another']
is to modify each element using an empty substitution, then print:
import re
for item in list:
charonly = re.sub('[0-9]','', item)
print charonly

This does not require "hiding" information in your string. It simply requires combining them with your other information (the numbers) at sorting time, and that can be done in many ways. Here's one:
# my strings, and the order I'd like them to have
my_strings = ["how", "there", "hello", "you", "are"]
my_ordering = [2, 1, 0, 3, 4]
# sort them
sorted_strings = [x for _, x in sorted(zip(my_ordering, my_strings))]
print(sorted_strings)

You can define a print function other than the built-in one. So this might not be exactly seek, what you want to do is better explained in the comments. But this is also a way.
def print2(string):
print "".join(letter for letter in string if letter.isalpha())
In you script, if you restrict the usage of the print function and only use the one you defined. It could be a solution.

I will ask to the question in the title:
Let's say that our string is:
ceva="123Password"
If you want to hider first 2:
ceva=ceva[2:]
ceva will be '3Password'
Now let's play with list of strings:
lista=["abc","ghi","def"]
for _,x in enumerate(sorted(lista)):
print(str(_)+x)
0abc
1def
2ghi
or
lista=["abc","ghi","def"]
for _,x in enumerate(sorted(lista)):
lista[_]=str(_)+x
>>> lista
['0abc', '1def', '2ghi']

Related

How can I generate a list and flatten it the same time in python?

This is more of a refactoring question, as the code works as is. But since I am still learning Python, I thought there would be a better way to do this, and I spent a few hours now digging into the other possibilities, but can't get anywhere.
So I have the following statement:
numbers = [re.split(' ?- ?', ticket.text.strip()) for ticket in tickets]
which obviously generates a list of lists. However, I want to have just a single list of the numbers taken out from that regex.
So this is the second line of code that flattens the above list (I found this solution here, on StackOverflow btw):
flat = [item for setlist in numbers for item in setlist]
Main thing I am trying to achieve is to have this on 1 single line. Otherwise, I could of course have a normal for .. in loop, that would append each number to numbers list, but I like keeping it on 1 line.
If this is the best it can get, I would also love to know that please.. :)
A better idea is to add another loop over re.split(' ?- ?', ticket.text.strip()) in the list comprehension:
flat = [x for ticket in tickets for x in re.split(' ?- ?', ticket.text.strip())]
It's also more efficient and cleaner.
By the way, you should use string methods instead of regex:
flat = [x.strip() for ticket in tickets for x in ticket.split('-')]
If you need to convert x to int, you may drop strip(), since int ignores leading and trailing whitespace.
flat = [int(x) for ticket in tickets for x in ticket.split('-')]
Well, let's work through this one step at a time.
As a set of partially-nested for-loops, your code would be:
numbers = []
for ticket in tickets:
numbers.append(re.split(' ?- ?', ticket.text.strip())
flat = []
for setlist in numbers:
for item in setlist:
flat.append(item)
Talking through it:
You have a list of tickets. Each ticket becomes one setlist when you apply the regex split to it. You then want to grab all the items in the setlist and put them in a single list. You don't actually need to have a list of all the setlists (what you called numbers) at any point - that's just an intermediate stage.
Refactoring this to be completely nested:
flat = []
for ticket in tickets:
for item in re.split(' ?- ?', ticket.text.strip()):
flat.append(item)
Now that we have a set of completely-nested for loops, it's trivial to refactor into a list or generator comprehension:
flat = [item for ticket in tickets for item in re.split(' ?- ?', ticket.text.strip())]
It's a fairly long single line, but it is a single line.
Incidentally, a regex might not be the best way to parse out numbers like that - especially if you want the actual numbers rather than strings. re.split() is slower than str.split(), and this split is simple enough that it can be done by the latter. If the numbers are integers, try:
flat = [int(item) for ticket in tickets for item in ticket.split('-'))]
And if they're floats, try:
flat = [float(item) for ticket in tickets for item in ticket.split('-'))]
This works because the int(str) and float(str) builtins automatically ignore whitespace at the start and end of a given string, so you don't need a regex to conditionally match that whitespace. The resulting numbers can still be inserted into strings if you need to do that, and should also take up somewhat less space in memory. If the numbers are integers, you lose nothing. If they're floats, you lose very little - you lose the original precision of the number, and you might run into the limits on float size if you're working with really big or really tiny stuff (but that's unlikely - see sys.float_info for what those limits are).
You can achieve it using chain and map in single line as:
list(chain(*map(lambda x: re.split(' ?- ?', x.text.strip()), tickets)))
Suggestion:
There is no need to use regex here, because you may achieve the same using split function of Python. Hence, your answer will become:
list(chain(*map(lambda x: x.text.replace(' ', '').split('-')), tickets)))
Explaination:
chain function from the itertools library is used to umwrap the list. Below is the sample example
>>> from itertools import chain
>>> my_nested_list = [[1,2,3], [4,5,6]]
>>> list(chain(*my_nested_list))
[1, 2, 3, 4, 5, 6]
Whereas map function is used to call the passed function (in this case lambda function) on each item of list.
>>> my_nested_list = [[1,2,3], [4,5,6]]
>>> map(lambda x: x[0], my_nested_list)
[1, 4]
And, split is used to split the content of string based on substring. For example:
>>> x = 'hey you - i am here'
>>> x.split('-')
['hey you ', ' i am here'] # Same answer as your regex
sum([re.split(' ?- ?', ticket.text.strip()) for ticket in tickets], [])
Just substitute the first expression for numbers in the second expression:
flat = [item for setlist in [re.split(' ?- ?', ticket.text.strip()) for ticket in tickets] for item in setlist]

Python: removing specific lines from an object

I have a bit of a weird question here.
I am using iperf to test performance between a device and a server. I get the results of this test over SSH, which I then want to parse into values using a parser that has already been made. However, there are several lines at the top of the results (which I read into an object of lines) that I don't want to go into the parser. I know exactly how many lines I need to remove from the top each time though. Is there any way to drop specific entries out of a list? Something like this in psuedo-python
print list
["line1","line2","line3","line4"]
list = list.drop([0 - 1])
print list
["line3","line4"]
If anyone knows anything I could use I would really appreciate you helping me out. The only thing I can think of is writing a loop to iterate through and make a new list only putting in what I need. Anyway, thanlks!
Michael
Slices:
l = ["line1","line2","line3","line4"]
print l[2:] # print from 2nd element (including) onwards
["line3","line4"]
Slices syntax is [from(included):to(excluded):step]. Each part is optional. So you can write [:] to get the whole list (or any iterable for that matter -- string and tuple as an example from the built-ins). You can also use negative indexes, so [:-2] means from beginning to the second last element. You can also step backwards, [::-1] means get all, but in reversed order.
Also, don't use list as a variable name. It overrides the built-in list class.
This is what the slice operator is for:
>>> before = [1,2,3,4]
>>> after = before[2:]
>>> print after
[3, 4]
In this instance, before[2:] says 'give me the elements of the list before, starting at element 2 and all the way until the end.'
(also -- don't use reserved words like list or dict as variable names -- doing that can lead to confusing bugs)
You can use slices for that:
>>> l = ["line1","line2","line3","line4"] # don't use "list" as variable name, it's a built-in.
>>> print l[2:] # to discard items up to some point, specify a starting index and no stop point.
['line3', 'line4']
>>> print l[:1] + l[3:] # to drop items "in the middle", join two slices.
['line1', 'line4']
why not use a basic list slice? something like:
list = list[3:] #everything from the 3 position to the end
You want del for that
del list[:2]
You can use "del" statment to remove specific entries :
del(list[0]) # remove entry 0
del(list[0:2]) # remove entries 0 and 1

Python: Looping starts from final item and ends with the first one

Is there any "pythonic way" to tell python to loop in a string (or list) starting from the last item and ending with the first one?
For example the word Hans i want python to read or sort it as snaH
Next, how can i tell pyhon the following: now from the string you resulted , search for 'a' find it ok , if you find 'n' follows 'a' , put '.' after 'n' and then print the original order of letters
The clearest and most pythonic way to do this is to used the reversed() builtin.
wrong_way = [1, 2, 3, 4]
for item in reversed(wrong_way):
print(item)
Which gives:
4
3
2
1
This is the best solution as not only will it generate a reversed iterator naturally, but it can also call the dedicated __reversed__() method if it exists, allowing for a more efficient reversal in some objects.
You can use wrong_way[::-1] to reverse a list, but this is a lot less readable in code, and potentially less efficient. It does, however, show the power of list slicing.
Note that reversed() provide iterators, so if you want to do this with a string, you will need to convert your result back to a string, which is fortunately easy, as you just do:
"".join(iterator)
e.g:
"".join(reversed(word))
The str.join() method takes an iterator and joins every element into a string, using the calling string as the separator, so here we use the empty string to place them back-to-back.
How about this?
>>> s = "Hans"
>>> for c in s[::-1]:
print c
s
n
a
H
Alternatively, if you want a new string that's the reverse of the first, try this:
>>> "".join(reversed("Hans"))
'snaH'
Sure, just use list_name[::-1]. e.g.
>>> l = ['one', 'two', 'three']
>>> for i in l[::-1]:
... print i
...
three
two
one

What is the best way to create a string array in python?

I'm relatively new to Python and it's libraries and I was wondering how I might create a string array with a preset size. It's easy in java but I was wondering how I might do this in python.
So far all I can think of is
strs = ['']*size
And some how when I try to call string methods on it, the debugger gives me an error X operation does not exist in object tuple.
And if it was in java this is what I would want to do.
String[] ar = new String[size];
Arrays.fill(ar,"");
Please help.
Error code
strs[sum-1] = strs[sum-1].strip('\(\)')
AttributeError: 'tuple' object has no attribute 'strip'
Question: How might I do what I can normally do in Java in Python while still keeping the code clean.
In python, you wouldn't normally do what you are trying to do. But, the below code will do it:
strs = ["" for x in range(size)]
In Python, the tendency is usually that one would use a non-fixed size list (that is to say items can be appended/removed to it dynamically). If you followed this, there would be no need to allocate a fixed-size collection ahead of time and fill it in with empty values. Rather, as you get or create strings, you simply add them to the list. When it comes time to remove values, you simply remove the appropriate value from the string. I would imagine you can probably use this technique for this. For example (in Python 2.x syntax):
>>> temp_list = []
>>> print temp_list
[]
>>>
>>> temp_list.append("one")
>>> temp_list.append("two")
>>> print temp_list
['one', 'two']
>>>
>>> temp_list.append("three")
>>> print temp_list
['one', 'two', 'three']
>>>
Of course, some situations might call for something more specific. In your case, a good idea may be to use a deque. Check out the post here: Python, forcing a list to a fixed size. With this, you can create a deque which has a fixed size. If a new value is appended to the end, the first element (head of the deque) is removed and the new item is appended onto the deque. This may work for what you need, but I don't believe this is considered the "norm" for Python.
The simple answer is, "You don't." At the point where you need something to be of fixed length, you're either stuck on old habits or writing for a very specific problem with its own unique set of constraints.
The best and most convenient method for creating a string array in python is with the help of NumPy library.
Example:
import numpy as np
arr = np.chararray((rows, columns))
This will create an array having all the entries as empty strings. You can then initialize the array using either indexing or slicing.
Are you trying to do something like this?
>>> strs = [s.strip('\(\)') for s in ['some\\', '(list)', 'of', 'strings']]
>>> strs
['some', 'list', 'of', 'strings']
But what is a reason to use fixed size? There is no actual need in python to use fixed size arrays(lists) so you always have ability to increase it's size using append, extend or decrease using pop, or at least you can use slicing.
x = ['' for x in xrange(10)]
strlist =[{}]*10
strlist[0] = set()
strlist[0].add("Beef")
strlist[0].add("Fish")
strlist[1] = {"Apple", "Banana"}
strlist[1].add("Cherry")
print(strlist[0])
print(strlist[1])
print(strlist[2])
print("Array size:", len(strlist))
print(strlist)
The error message says it all: strs[sum-1] is a tuple, not a string. If you show more of your code someone will probably be able to help you. Without that we can only guess.
Sometimes I need a empty char array. You cannot do "np.empty(size)" because error will be reported if you fill in char later. Then I usually do something quite clumsy but it is still one way to do it:
# Suppose you want a size N char array
charlist = [' ']*N # other preset character is fine as well, like 'x'
chararray = np.array(charlist)
# Then you change the content of the array
chararray[somecondition1] = 'a'
chararray[somecondition2] = 'b'
The bad part of this is that your array has default values (if you forget to change them).
def _remove_regex(input_text, regex_pattern):
findregs = re.finditer(regex_pattern, input_text)
for i in findregs:
input_text = re.sub(i.group().strip(), '', input_text)
return input_text
regex_pattern = r"\buntil\b|\bcan\b|\bboat\b"
_remove_regex("row and row and row your boat until you can row no more", regex_pattern)
\w means that it matches word characters, a|b means match either a or b, \b represents a word boundary
If you want to take input from user here is the code
If each string is given in new line:
strs = [input() for i in range(size)]
If the strings are separated by spaces:
strs = list(input().split())

Add specific columns to a single row list (might be a little basic)

I am designing a password recovery program, and I want to make it "right"/modular enough to be plugged into other programs, so I am trying to avoid ugly hacks.
Here's the rundown: I have a list with a string
myString = "Hey what's up?"
myString2DList = [
myString,
]
Now I have a 2D list with a single row. All I want to do is add columns (could be lists themselves) under the users-specified index
So, there could be say 3 indexes (that correspond to a column)
like: 0,4,6 (H,w,a)
and now I just want to dynamically append anything to those columns. I have done searches and not much has helped (I did see some promising posts that mentioned that the Dict data type might be better to use here), and I feel totally stuck...
Edit/To clarify:
Basically, the first row will be representing a password that the user wants to recover. Let's say the user can't remember their password but can remember at least a few characters. I want the columns to represent each possible alternative for each character, then my script will brute force the password with constraints. I already coded an ugly script that does the same thing, I just have to recode the thing for every password, I want to make it dynamic because it REALLY came in handy.
Thanks!
It's not immediately clear to me what you're trying to do. The closest thing to a 2D array that Python has is a list of lists. What you have now is single list, though, not a 2D list. A 2D list would look like this (replace these names with more meaningful ones):
list_of_lists = [[header0, header1, header2 ],
[r1c0data, r1c1data, r1c2data],
[r2c0data, r2c1data, r2c2data]]
To append a row, you just add a list (i.e. list_of_lists.append(new_list)). To append a column, you'd have to add an item to the end of teach list like so:
c4data = [header3, r1c3data, r2c3data]
for i, row in enumerate(list_of_lists):
row.append(c4data[i])
If you really want 2D arrays, you might be better off using numpy.array.
But is your desire to index individual rows by column heading? If so, you'd be better off using a list of dictionaries:
list_of_dicts = [{'column0':r0c0data, 'column1':r0c1data, 'column2':r0c2data},
{'column0':r1c0data, 'column1':r1c1data, 'column2':r1c2data}]
You could even cut that down to one dict, using tuples to address individual elements:
tuple_key_dict = {(0, 0):r0c0data, (0, 1):r0c1data, (0, 2):r0c2data,
(0, 1):r0c1data, (1, 1):r1c1data, (1, 2):r1c2data}
Each of these methods are suited to different tasks. You might even need to use a database. We need to know more about what you're doing to tell you.
Ok, to do what you want, there's no need for a list of lists at all. Just create a list of strings, each of which represents the possible characters at the corresponding index of the password string. So for example, say the user used a password that was a combination of the German and English words for 'appletree', but can't remember which combination:
>>> char_list = [''.join(set((a, b))) for a, b in zip('apfelbaum', 'appletree')]
>>> char_list
['a', 'p', 'pf', 'el', 'el', 'bt', 'ar', 'eu', 'em']
char_list now contains all possible letters at each index. To generate all possible passwords, all you need is the cartesian product of these strings:
>>> import itertools
>>> password_list = [''.join(tup) for tup in itertools.product(*char_list)]
>>> print 'appletree' in password_list
True
>>> print 'apfelbaum' in password_list
True
>>> print 'apfletrum' in password_list
True
If I under stand your question properly. Take a look at this to see if it will work for you.
str_1 = 'Hey What\'s Up?'
str_2 = 'Hey, Not Much!'
my2dlist = [[str_1]] #Note the double brackets
my2dlist.append([str_2]) # Note that you are appending a List to the other list.
print my2dlist # Yields: [["Hey What's Up?"], ['Hey, Not Much!']]
my2dlist[0].append(-1)
print my2dlist # Yields: [["Hey What's Up?", -1], ['Hey, Not Much!']]
Note that the list of lists gives you the ability to use whatever python type you need to associate with. If you need more explanation let me know and I can go into more detail.
Cheers!

Categories