Basic string slicing from indices - string

I will state the obvious that I am a beginner. I should also mention that I have been coding in Zybooks, which affects things. My textbook hasn't helped me much
I tried sub_lyric= rhyme_lyric[ : ]
Zybooks should be able to input an index number can get only that part of the sentence but my book doesnt explain how to do that. If it throws a [4:7] then it would output cow. Hopefully I have exolained everything well.

You need to set there:
sub_lyric = rhyme_lyric[start_index:end_index]
The string is as a sequence of characters and you can use string slicing to extract any sub-text from the main one. As you have observed:
sub_lyric = rhyme_lyric[:]
will copy the entire content of rhyme_lyric to sub_lyric.
To select only a portion of the text, specify the start_index (strings start with index 0) to end_index (not included).
sub_lyric = rhyme_lyric[4:7]
will extract characters in rhyme_lyric from position 4 (included) to position 7 (not included) so the result will be cow.
You can check more on string slicing here: Python 3 introduction

Related

Python - how to recursively search a variable substring in texts that are elements of a list

let me explain better what I mean in the title.
Examples of strings where to search (i.e. strings of variable lengths
each one is an element of a list; very large in reality):
STRINGS = ['sftrkpilotndkpilotllptptpyrh', 'ffftapilotdfmmmbtyrtdll', 'gftttepncvjspwqbbqbthpilotou', 'htfrpilotrtubbbfelnxcdcz']
The substring to find, which I know is for sure:
contained in each element of STRINGS
is also contained in a SOURCE string
is of a certain fixed LENGTH (5 characters in this example).
SOURCE = ['gfrtewwxadasvpbepilotzxxndffc']
I am trying to write a Python3 program that finds this hidden word of 5 characters that is in SOURCE and at what position(s) it occurs in each element of STRINGS.
I am also trying to store the results in an array or a dictionary (I do not know what is more convenient at the moment).
Moreover, I need to perform other searches of the same type but with different LENGTH values, so this value should be provided by a variable in order to be of more general use.
I know that the first point has been already solved in previous posts, but
never (as far as I know) together with the second point, which is the part of the code I could not be able to deal with successfully (I do not post my code because I know it is just too far from being fixable).
Any help from this great community is highly appreciated.
-- Maurizio
You can iterate over the source string and for each sub-string use the re module to find the positions within each of the other strings. Then if at least one occurrence was found for each of the strings, yield the result:
import re
def find(source, strings, length):
for i in range(len(source) - length):
sub = source[i:i+length]
positions = {}
for s in strings:
# positions[s] = [m.start() for m in re.finditer(re.escape(sub), s)]
positions[s] = [i for i in range(len(s)) if s.startswith(sub, i)] # Using built-in functions.
if not positions[s]:
break
else:
yield sub, positions
And the generator can be used as illustrated in the following example:
import pprint
pprint.pprint(dict(find(
source='gfrtewwxadasvpbepilotzxxndffc',
strings=['sftrkpilotndkpilotllptptpyrh',
'ffftapilotdfmmmbtyrtdll',
'gftttepncvjspwqbbqbthpilotou',
'htfrpilotrtubbbfelnxcdcz'],
length=5
)))
which produces the following output:
{'pilot': {'ffftapilotdfmmmbtyrtdll': [5],
'gftttepncvjspwqbbqbthpilotou': [21],
'htfrpilotrtubbbfelnxcdcz': [4],
'sftrkpilotndkpilotllptptpyrh': [5, 13]}}

Set position according part of an objectname

I'm trying to script something in blender3D using python.
I've got a bunch of objects in my scene and want to translate them using a the numerical part of their objectname.
First of all i collect objects from the scene by matching a part of their name.
root_obj = [obj for obj in scene.objects if fnmatch.fnmatchcase(obj.name, "*_Root")]
This gives me a list with:[bpy.data.objects['01_Root'],bpy.data.objects['02_Root'],bpy.data.objects['03_Root'],bpy.data.objects['00_Root']]
My goal is to move these objects 15x their corresponding part of the name. So '00_Root' doesnt have to move, but '01_Root' has to move 15 blender units and '02_Root' 30 blender units.
How do i exctract the numberpart of the names and use them as translation values.
I'm a pretty newb with python so i would appreciate all the help i can get.
A string is a list of characters, each character can be accessed by index starting with 0, get the first character with name[0], the second with name[1]. As with any list you can use slicing to get a portion of the list. If the value is always the first two characters you can get the value with name[:2] you can them turn that into an integer with int() or a float with float(). Combined that becomes,
val = int(name[:2])
You then have a number you can calculate the new location with.
obj.location.x = val * 15
If the number of digits in the name might vary you can use split() to break the string on a specific separating character. This returns a list of items between the specified character, so if you want the first item to turn into an integer.
name = '02_item'
val = int(name.split('_')[0])
Using split also allows multiple values in a name.
name = '2_12_item'
val1 = int(name.split('_')[0])
val2 = int(name.split('_')[1])

Adding Hyphen within a spliced string

Continuing from my last question (which, btw, thanks for the help!), I'm stuck on how to add a hyphen to separate my string. Here's what I have so far:
original = "1234567890"
def fixPhoneNum(original):
original = list(original)
original[0], original[9] = original[9], original[0]
original[1:5], original[5:8] = original[5:8], original[1:5]
original = ''.join(original)
original = print(original[0:3], end="-"), print(original[3:7], end="-"), print(original[5:9])
return
Edit The above code doesn't give me the result I'm looking for
So basically, I took the original string of numbers, switched the first and last and the intermediary values with each other. Now I want to separate the first 3 digits, the next 3 digits with a hyphen.
Any help? This is driving me crazy.
Thanks!
I do not quite understand the rule for character ordering in your question.
Here is a simpler example of str.format function which accepts "0123" and produces "30-21" permutation with a hyphen. Hope it answers the question.
instr = "0123"
outstr = '{0[3]}{0[0]}-{0[2]}{0[1]}'.format(instr)
If you are not familiar with format strings, start with examples in the docs: https://docs.python.org/3/library/string.html#formatexamples

String matching without using builtin functions

I want to search for a query (a string) in a subject (another string).
The query may appear in whole or in parts, but will not be rearranged. For instance, if the query is 'da', and the subject is 'dura', it is still a match.
I am not allowed to use string functions like strfind or find.
The constraints make this actually quite straightforward with a single loop. Imagine you have two indices initially pointing at the first character of both strings, now compare them - if they don't match, increment the subject index and try again. If they do, increment both. If you've reached the end of the query at that point, you've found it. The actual implementation should be simple enough, and I don't want to do all the work for you ;)
If this is homework, I suggest you look at the explanation which precedes the code and then try for yourself, before looking at the actual code.
The code below looks for all occurrences of chars of the query string within the subject string (variables m; and related ii, jj). It then tests all possible orders of those occurrences (variable test). An order is "acceptable" if it contains all desired chars (cond1) in increasing positions (cond2). The result (variable result) is affirmative if there is at least one acceptable order.
subject = 'this is a test string';
query = 'ten';
m = bsxfun(#eq, subject.', query);
%'// m: test if each char of query equals each char of subject
[ii jj] = find(m);
jj = jj.'; %'// ii: which char of query is found within subject...
ii = ii.'; %'// jj: ... and at which position
test = nchoosek(1:numel(jj),numel(query)).'; %'// test all possible orders
cond1 = all(jj(test) == repmat((1:numel(query)).',1,size(test,2)));
%'// cond1: for each order, are all chars of query found in subject?
cond2 = all(diff(ii(test))>0);
%// cond2: for each order, are the found chars in increasing positions?
result = any(cond1 & cond2); %// final result: 1 or 0
The code could be improved by using a better approach as regards to test, i.e. not testing all possible orders given by nchoosek.
Matlab allows you to view the source of built-in functions, so you could always try reading the code to see how the Matlab developers did it (although it will probably be very complex). (thanks Luis for the correction)
Finding a string in another string is a basic computer science problem. You can read up on it in any number of resources, such as Wikipedia.
Your requirement of non-rearranging partial matches recalls the bioinformatics problem of mapping splice variants to a genomic sequence.
You may solve your problem by using a sequence alignment algorithm such as Smith-Waterman, modified to work with all English characters and not just DNA bases.
Is this question actually from bioinformatics? If so, you should tag it as such.

function to confirm the presence of both letters and numbers/ Ignoring excedents

So, I'm trying to build up a program with MATLAB according to some indications from my teacher and I came up with some obstacles which would give me a better grade if I could get them right. Here they are:
The user is asked to insert a string but it can't have more than 20 characters. If it does, the excedents will be ignored and the string is saved with the first 20 characters the user inserted. How do I ignore the excedents in a string and save it anyway?
isletter is a function that tells us if the elements are all letters. In this program, the user is asked to insert a string that needs to include both numbers and letters, so that strings with just letters or just numbers are excluded, and then I'll use a while to keep asking for a string with these characteristics.
Could you please help me? This is my first semester with MATLAB. Thank you!
If you want to disallow characters other than letters and numbers (i.e. '/#!' or whitespace) and require that the string they enter has to have at least 1 letter and 1 number, then you can use the ISSTRPROP function (which is more general than ISLETTER) to check for other types of characters. The idea to use INPUTDLG to prompt for the string (as suggested in Aabaz's answer) is a good one, so here's a nice condensed solution using INPUTDLG that achieves what you want:
answer = ''; %# Initialize answer to be an empty string
while any(~isstrprop(answer, 'alphanum')) || ... %# Check for alphanumeric chars
~any(isletter(answer)) || ... %# Check for at least 1 letter
~any(isstrprop(answer, 'digit')) %# Check for at least 1 number
answer = inputdlg('Enter string:'); %# Prompt for input
answer = answer{1}(1:min(20, end)); %# Trim answer to max of 20 chars
end
Note how the functions MIN and END are used to trim the string to 20 characters.
For the first part of your problem you can use the Matlab function inputdlg which prompts a dialog box asking for user input. Then you can trim the input as you like.
For the second part of your problem the function isletter that you mentioned will tell you for each character individually if they are alphabetic letters, so you could sum that result and check if it is between 1 and 19 for example. That will tell you that your string contains both letters and numbers.
Finally, you can put your code inside a while loop and change a variable when your conditions are met so that you can break outside of the loop.
This example code demonstrates this:
tryagain=1;
while(tryagain)
answer=inputdlg('Insert a 20 character string that contains both letters and numbers','User input');
answer=answer{1};
if(numel(answer)>20)
answer=answer(1:20);
end
letters=sum(isletter(answer));
numbers=sum(~arrayfun(#(x)isempty(str2num(x)),answer));
if(letters>0 && numbers>0)
tryagain=0;
end
end

Resources