Python: pythonic way to find last position in string that does not match regexIs there a way to run Python on...
Please, smoke with good manners
"The cow" OR "a cow" OR "cows" in this context
Pulling the rope with one hand is as heavy as with two hands?
How can I use Monero RPC via Python
Why is current rating for multicore cable lower than single core with the same cross section?
Counterexample: a pair of linearly ordered sets that are isomorphic to subsets of the other, but not isomorphic between them
How can the Zone of Truth spell be defeated without the caster knowing?
Why was Germany not as successful as other Europeans in establishing overseas colonies?
What is the difference between `a[bc]d` (brackets) and `a{b,c}d` (braces)?
Rivers without rain
What is the most expensive material in the world that could be used to create Pun-Pun's lute?
How to make a pipeline wait for end-of-file or stop after an error?
How would one muzzle a full grown polar bear in the 13th century?
Is there a way to get a compiler for the original B programming language?
What does YCWCYODFTRFDTY mean?
Do I have an "anti-research" personality?
How can I place the product on a social media post better?
Question relating to a number theoretic function
Packing rectangles: Does rotation ever help?
Can someone publish a story that happened to you?
How to pronounce 'C++' in Spanish
How to creep the reader out with what seems like a normal person?
Minimum value of 4 digit number divided by sum of its digits
Pressure to defend the relevance of one's area of mathematics
Python: pythonic way to find last position in string that does not match regex
Is there a way to run Python on Android?Finding the index of an item given a list containing it in PythonNicest way to pad zeroes to a stringDoes Python have a ternary conditional operator?How to substring a string in Python?Getting the last element of a list in PythonReverse a string in PythonDoes Python have a string 'contains' substring method?How do I lowercase a string in Python?Most elegant way to check if the string is empty in Python?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
In Python I try to find the last position in an arbitrary string that does not match a given pattern, which is specified as regex pattern (that includes the "not" in the match). For example, with the string uiae1iuae200, and the pattern of not being a number (regex pattern in Python for this would be [^0-9]), I would need '8' (the last 'e' before the '200') as result. What is the most pythonic way to achieve this?
As it's a little tricky to quickly find method documentation and the best suited method for something in the Python docs (due to method docs being somewhere in the middle of the corresponding page, like re.search() in the re page), the best way I quickly found myself is using re.search() - but the current form simply must be a suboptimal way of doing it:
import re
string = 'uiae1iuae200' # the string to investigate
len(string) - re.search(r'[^0-9]', string[::-1]).start()
I am not satisfied with this for two reasons: a) I need to reverse string before using it with [::-1], and b) I also need to reverse the resulting position (subtracting it from len(string) because of having reversed the string before. There needs to be better ways for this, likely even with the result of re.search().
I am aware of re.search(...).end() over .start(), but re.search() seems to split the results into groups, for which I did not quickly find a not-cumbersome way to apply it to the last matched group. Without specifying the group, .start(), .end(), etc, seem to always match the first group, which does not have the position information about the last match. However, selecting the group seems to at first require the return value to temporarily be saved in a variable (which prevents neat one-liners), as I would need to access both the information about selecting the last group and then to select .end() from this group.
What's your pythonic solution to this? I would value being pythonic more than having the most optimized runtime.
Update
The solution should be functional also in corner cases, like 123 (no position that matches the regex), empty string, etc. It should not crash e.g. because of selecting the last index of an empty list. However, as even my ugly answer above in the question would need more than one line for this, I guess a one-liner might be impossible for this (simply because one needs to check the return value of re.search() or re.finditer() before handling it). I'll accept pythonic multi-line solutions to this answer for this reason.
python regex string regex-negation
add a comment |
In Python I try to find the last position in an arbitrary string that does not match a given pattern, which is specified as regex pattern (that includes the "not" in the match). For example, with the string uiae1iuae200, and the pattern of not being a number (regex pattern in Python for this would be [^0-9]), I would need '8' (the last 'e' before the '200') as result. What is the most pythonic way to achieve this?
As it's a little tricky to quickly find method documentation and the best suited method for something in the Python docs (due to method docs being somewhere in the middle of the corresponding page, like re.search() in the re page), the best way I quickly found myself is using re.search() - but the current form simply must be a suboptimal way of doing it:
import re
string = 'uiae1iuae200' # the string to investigate
len(string) - re.search(r'[^0-9]', string[::-1]).start()
I am not satisfied with this for two reasons: a) I need to reverse string before using it with [::-1], and b) I also need to reverse the resulting position (subtracting it from len(string) because of having reversed the string before. There needs to be better ways for this, likely even with the result of re.search().
I am aware of re.search(...).end() over .start(), but re.search() seems to split the results into groups, for which I did not quickly find a not-cumbersome way to apply it to the last matched group. Without specifying the group, .start(), .end(), etc, seem to always match the first group, which does not have the position information about the last match. However, selecting the group seems to at first require the return value to temporarily be saved in a variable (which prevents neat one-liners), as I would need to access both the information about selecting the last group and then to select .end() from this group.
What's your pythonic solution to this? I would value being pythonic more than having the most optimized runtime.
Update
The solution should be functional also in corner cases, like 123 (no position that matches the regex), empty string, etc. It should not crash e.g. because of selecting the last index of an empty list. However, as even my ugly answer above in the question would need more than one line for this, I guess a one-liner might be impossible for this (simply because one needs to check the return value of re.search() or re.finditer() before handling it). I'll accept pythonic multi-line solutions to this answer for this reason.
python regex string regex-negation
last position that does 'not' or does match regex? Lastematches[^0-9]pattern.
– dgumo
3 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be[^0-9]. I'll update the question.
– geekoverdose
2 hours ago
Shoulds = 'uiae1iuae200aaaaaaaa'return the index of last char before a digit akae(8) or the last char akaa(19)?
– ruohola
2 hours ago
1
Withuiae1iuae200aaaaaaaait should return the last position in the string, means19.
– geekoverdose
2 hours ago
add a comment |
In Python I try to find the last position in an arbitrary string that does not match a given pattern, which is specified as regex pattern (that includes the "not" in the match). For example, with the string uiae1iuae200, and the pattern of not being a number (regex pattern in Python for this would be [^0-9]), I would need '8' (the last 'e' before the '200') as result. What is the most pythonic way to achieve this?
As it's a little tricky to quickly find method documentation and the best suited method for something in the Python docs (due to method docs being somewhere in the middle of the corresponding page, like re.search() in the re page), the best way I quickly found myself is using re.search() - but the current form simply must be a suboptimal way of doing it:
import re
string = 'uiae1iuae200' # the string to investigate
len(string) - re.search(r'[^0-9]', string[::-1]).start()
I am not satisfied with this for two reasons: a) I need to reverse string before using it with [::-1], and b) I also need to reverse the resulting position (subtracting it from len(string) because of having reversed the string before. There needs to be better ways for this, likely even with the result of re.search().
I am aware of re.search(...).end() over .start(), but re.search() seems to split the results into groups, for which I did not quickly find a not-cumbersome way to apply it to the last matched group. Without specifying the group, .start(), .end(), etc, seem to always match the first group, which does not have the position information about the last match. However, selecting the group seems to at first require the return value to temporarily be saved in a variable (which prevents neat one-liners), as I would need to access both the information about selecting the last group and then to select .end() from this group.
What's your pythonic solution to this? I would value being pythonic more than having the most optimized runtime.
Update
The solution should be functional also in corner cases, like 123 (no position that matches the regex), empty string, etc. It should not crash e.g. because of selecting the last index of an empty list. However, as even my ugly answer above in the question would need more than one line for this, I guess a one-liner might be impossible for this (simply because one needs to check the return value of re.search() or re.finditer() before handling it). I'll accept pythonic multi-line solutions to this answer for this reason.
python regex string regex-negation
In Python I try to find the last position in an arbitrary string that does not match a given pattern, which is specified as regex pattern (that includes the "not" in the match). For example, with the string uiae1iuae200, and the pattern of not being a number (regex pattern in Python for this would be [^0-9]), I would need '8' (the last 'e' before the '200') as result. What is the most pythonic way to achieve this?
As it's a little tricky to quickly find method documentation and the best suited method for something in the Python docs (due to method docs being somewhere in the middle of the corresponding page, like re.search() in the re page), the best way I quickly found myself is using re.search() - but the current form simply must be a suboptimal way of doing it:
import re
string = 'uiae1iuae200' # the string to investigate
len(string) - re.search(r'[^0-9]', string[::-1]).start()
I am not satisfied with this for two reasons: a) I need to reverse string before using it with [::-1], and b) I also need to reverse the resulting position (subtracting it from len(string) because of having reversed the string before. There needs to be better ways for this, likely even with the result of re.search().
I am aware of re.search(...).end() over .start(), but re.search() seems to split the results into groups, for which I did not quickly find a not-cumbersome way to apply it to the last matched group. Without specifying the group, .start(), .end(), etc, seem to always match the first group, which does not have the position information about the last match. However, selecting the group seems to at first require the return value to temporarily be saved in a variable (which prevents neat one-liners), as I would need to access both the information about selecting the last group and then to select .end() from this group.
What's your pythonic solution to this? I would value being pythonic more than having the most optimized runtime.
Update
The solution should be functional also in corner cases, like 123 (no position that matches the regex), empty string, etc. It should not crash e.g. because of selecting the last index of an empty list. However, as even my ugly answer above in the question would need more than one line for this, I guess a one-liner might be impossible for this (simply because one needs to check the return value of re.search() or re.finditer() before handling it). I'll accept pythonic multi-line solutions to this answer for this reason.
python regex string regex-negation
python regex string regex-negation
edited 2 hours ago
geekoverdose
asked 3 hours ago
geekoverdosegeekoverdose
727615
727615
last position that does 'not' or does match regex? Lastematches[^0-9]pattern.
– dgumo
3 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be[^0-9]. I'll update the question.
– geekoverdose
2 hours ago
Shoulds = 'uiae1iuae200aaaaaaaa'return the index of last char before a digit akae(8) or the last char akaa(19)?
– ruohola
2 hours ago
1
Withuiae1iuae200aaaaaaaait should return the last position in the string, means19.
– geekoverdose
2 hours ago
add a comment |
last position that does 'not' or does match regex? Lastematches[^0-9]pattern.
– dgumo
3 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be[^0-9]. I'll update the question.
– geekoverdose
2 hours ago
Shoulds = 'uiae1iuae200aaaaaaaa'return the index of last char before a digit akae(8) or the last char akaa(19)?
– ruohola
2 hours ago
1
Withuiae1iuae200aaaaaaaait should return the last position in the string, means19.
– geekoverdose
2 hours ago
last position that does 'not' or does match regex? Last
e matches [^0-9] pattern.– dgumo
3 hours ago
last position that does 'not' or does match regex? Last
e matches [^0-9] pattern.– dgumo
3 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be
[^0-9]. I'll update the question.– geekoverdose
2 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be
[^0-9]. I'll update the question.– geekoverdose
2 hours ago
Should
s = 'uiae1iuae200aaaaaaaa' return the index of last char before a digit aka e (8) or the last char aka a (19)?– ruohola
2 hours ago
Should
s = 'uiae1iuae200aaaaaaaa' return the index of last char before a digit aka e (8) or the last char aka a (19)?– ruohola
2 hours ago
1
1
With
uiae1iuae200aaaaaaaa it should return the last position in the string, means 19.– geekoverdose
2 hours ago
With
uiae1iuae200aaaaaaaa it should return the last position in the string, means 19.– geekoverdose
2 hours ago
add a comment |
3 Answers
3
active
oldest
votes
You can use re.finditer to extract start positions of all matches and return the last one from list. Try this Python code (apologies if it is non-Pythonic as I am quite new to Python),
import re
print([m.start(0) for m in re.finditer(r'D', 'uiae1iuae200')][-1])
Prints,
8
Edit:
For making the solution a bit more elegant to behave properly in for all kind of inputs, here is the updated code. Now the solution goes in two lines as the check has to be performed if list is empty then it will print -1 else the index value.
import re
arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']
for s in arr:
lst = [m.start() for m in re.finditer(r'D', s)]
print(s, '-->', lst[-1] if len(lst) > 0 else -1)
Prints the following, where if no such index is found then prints -1 instead of index.
--> -1
123 --> -1
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
Upside: one-liner possible (move the[-1]one line up). Downside: list comprehension required. Still a very good take on my question I guess!
– geekoverdose
2 hours ago
This will throw anIndexErroron the new requirement casestring = '123'.
– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
|
show 1 more comment
This is a really clean way, which works perfectly with the new requirement:
(printing None with no errors when string = '123')
import re
string = 'uiae1iuae200'
ls = list(re.finditer(r'[^0-9]', string))
print(ls[-1].start() if ls else None)
Output:
8
Or alternatively using collections.deque:
import re
from collections import deque
string = 'uiae1iuae200'
que = deque(re.finditer(r'[^0-9]', string), maxlen=1)
print(que.pop().start() if que else None)
Here's my original very pythonic and efficient answer:
(Which unfortunately will throw a ValueError when string = '123')
import re
string = 'uiae1iuae200'
*_, last = re.finditer(r'[^0-9]', string)
print(last.start())
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
@Rightleg True, but OP saidI would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
add a comment |
This does not look Pythonic because it's not a one-liner, and it uses range(len(foo)), but it's pretty straightforward and probably not too inefficient.
def last_match(pattern, string):
for i in range(1, len(string) + 1):
substring = string[-i:]
if re.match(pattern, substring):
return len(string) - i
The idea is to iterate over the suffixes of string from the shortest to the longest, and to check if it matches pattern.
Since we're checking from the end, we know for sure that the first substring we meet that matches the pattern is the last.
2
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
This is not very readable, uses therange(len(foo))antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.
– ruohola
2 hours ago
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
|
show 3 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55890245%2fpython-pythonic-way-to-find-last-position-in-string-that-does-not-match-regex%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use re.finditer to extract start positions of all matches and return the last one from list. Try this Python code (apologies if it is non-Pythonic as I am quite new to Python),
import re
print([m.start(0) for m in re.finditer(r'D', 'uiae1iuae200')][-1])
Prints,
8
Edit:
For making the solution a bit more elegant to behave properly in for all kind of inputs, here is the updated code. Now the solution goes in two lines as the check has to be performed if list is empty then it will print -1 else the index value.
import re
arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']
for s in arr:
lst = [m.start() for m in re.finditer(r'D', s)]
print(s, '-->', lst[-1] if len(lst) > 0 else -1)
Prints the following, where if no such index is found then prints -1 instead of index.
--> -1
123 --> -1
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
Upside: one-liner possible (move the[-1]one line up). Downside: list comprehension required. Still a very good take on my question I guess!
– geekoverdose
2 hours ago
This will throw anIndexErroron the new requirement casestring = '123'.
– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
|
show 1 more comment
You can use re.finditer to extract start positions of all matches and return the last one from list. Try this Python code (apologies if it is non-Pythonic as I am quite new to Python),
import re
print([m.start(0) for m in re.finditer(r'D', 'uiae1iuae200')][-1])
Prints,
8
Edit:
For making the solution a bit more elegant to behave properly in for all kind of inputs, here is the updated code. Now the solution goes in two lines as the check has to be performed if list is empty then it will print -1 else the index value.
import re
arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']
for s in arr:
lst = [m.start() for m in re.finditer(r'D', s)]
print(s, '-->', lst[-1] if len(lst) > 0 else -1)
Prints the following, where if no such index is found then prints -1 instead of index.
--> -1
123 --> -1
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
Upside: one-liner possible (move the[-1]one line up). Downside: list comprehension required. Still a very good take on my question I guess!
– geekoverdose
2 hours ago
This will throw anIndexErroron the new requirement casestring = '123'.
– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
|
show 1 more comment
You can use re.finditer to extract start positions of all matches and return the last one from list. Try this Python code (apologies if it is non-Pythonic as I am quite new to Python),
import re
print([m.start(0) for m in re.finditer(r'D', 'uiae1iuae200')][-1])
Prints,
8
Edit:
For making the solution a bit more elegant to behave properly in for all kind of inputs, here is the updated code. Now the solution goes in two lines as the check has to be performed if list is empty then it will print -1 else the index value.
import re
arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']
for s in arr:
lst = [m.start() for m in re.finditer(r'D', s)]
print(s, '-->', lst[-1] if len(lst) > 0 else -1)
Prints the following, where if no such index is found then prints -1 instead of index.
--> -1
123 --> -1
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19
You can use re.finditer to extract start positions of all matches and return the last one from list. Try this Python code (apologies if it is non-Pythonic as I am quite new to Python),
import re
print([m.start(0) for m in re.finditer(r'D', 'uiae1iuae200')][-1])
Prints,
8
Edit:
For making the solution a bit more elegant to behave properly in for all kind of inputs, here is the updated code. Now the solution goes in two lines as the check has to be performed if list is empty then it will print -1 else the index value.
import re
arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']
for s in arr:
lst = [m.start() for m in re.finditer(r'D', s)]
print(s, '-->', lst[-1] if len(lst) > 0 else -1)
Prints the following, where if no such index is found then prints -1 instead of index.
--> -1
123 --> -1
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19
edited 20 mins ago
answered 3 hours ago
Pushpesh Kumar RajwanshiPushpesh Kumar Rajwanshi
13.7k21331
13.7k21331
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
Upside: one-liner possible (move the[-1]one line up). Downside: list comprehension required. Still a very good take on my question I guess!
– geekoverdose
2 hours ago
This will throw anIndexErroron the new requirement casestring = '123'.
– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
|
show 1 more comment
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
Upside: one-liner possible (move the[-1]one line up). Downside: list comprehension required. Still a very good take on my question I guess!
– geekoverdose
2 hours ago
This will throw anIndexErroron the new requirement casestring = '123'.
– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
1
1
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
Nice answer, edited it a bit to remove unnecessary index shifting.
– ruohola
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
@ruohola: Many thanks for improving my answer. Logically I had the idea but not exactly how to do it as new to Python. I appreciate.
– Pushpesh Kumar Rajwanshi
2 hours ago
1
1
Upside: one-liner possible (move the
[-1] one line up). Downside: list comprehension required. Still a very good take on my question I guess!– geekoverdose
2 hours ago
Upside: one-liner possible (move the
[-1] one line up). Downside: list comprehension required. Still a very good take on my question I guess!– geekoverdose
2 hours ago
This will throw an
IndexError on the new requirement case string = '123'.– ruohola
1 hour ago
This will throw an
IndexError on the new requirement case string = '123'.– ruohola
1 hour ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
@ruohola: Ok, just saw the requirement got a bit updated. Let me update my solution to take care that.
– Pushpesh Kumar Rajwanshi
23 mins ago
|
show 1 more comment
This is a really clean way, which works perfectly with the new requirement:
(printing None with no errors when string = '123')
import re
string = 'uiae1iuae200'
ls = list(re.finditer(r'[^0-9]', string))
print(ls[-1].start() if ls else None)
Output:
8
Or alternatively using collections.deque:
import re
from collections import deque
string = 'uiae1iuae200'
que = deque(re.finditer(r'[^0-9]', string), maxlen=1)
print(que.pop().start() if que else None)
Here's my original very pythonic and efficient answer:
(Which unfortunately will throw a ValueError when string = '123')
import re
string = 'uiae1iuae200'
*_, last = re.finditer(r'[^0-9]', string)
print(last.start())
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
@Rightleg True, but OP saidI would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
add a comment |
This is a really clean way, which works perfectly with the new requirement:
(printing None with no errors when string = '123')
import re
string = 'uiae1iuae200'
ls = list(re.finditer(r'[^0-9]', string))
print(ls[-1].start() if ls else None)
Output:
8
Or alternatively using collections.deque:
import re
from collections import deque
string = 'uiae1iuae200'
que = deque(re.finditer(r'[^0-9]', string), maxlen=1)
print(que.pop().start() if que else None)
Here's my original very pythonic and efficient answer:
(Which unfortunately will throw a ValueError when string = '123')
import re
string = 'uiae1iuae200'
*_, last = re.finditer(r'[^0-9]', string)
print(last.start())
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
@Rightleg True, but OP saidI would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
add a comment |
This is a really clean way, which works perfectly with the new requirement:
(printing None with no errors when string = '123')
import re
string = 'uiae1iuae200'
ls = list(re.finditer(r'[^0-9]', string))
print(ls[-1].start() if ls else None)
Output:
8
Or alternatively using collections.deque:
import re
from collections import deque
string = 'uiae1iuae200'
que = deque(re.finditer(r'[^0-9]', string), maxlen=1)
print(que.pop().start() if que else None)
Here's my original very pythonic and efficient answer:
(Which unfortunately will throw a ValueError when string = '123')
import re
string = 'uiae1iuae200'
*_, last = re.finditer(r'[^0-9]', string)
print(last.start())
This is a really clean way, which works perfectly with the new requirement:
(printing None with no errors when string = '123')
import re
string = 'uiae1iuae200'
ls = list(re.finditer(r'[^0-9]', string))
print(ls[-1].start() if ls else None)
Output:
8
Or alternatively using collections.deque:
import re
from collections import deque
string = 'uiae1iuae200'
que = deque(re.finditer(r'[^0-9]', string), maxlen=1)
print(que.pop().start() if que else None)
Here's my original very pythonic and efficient answer:
(Which unfortunately will throw a ValueError when string = '123')
import re
string = 'uiae1iuae200'
*_, last = re.finditer(r'[^0-9]', string)
print(last.start())
edited 10 mins ago
answered 2 hours ago
ruoholaruohola
2,117424
2,117424
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
@Rightleg True, but OP saidI would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
add a comment |
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
@Rightleg True, but OP saidI would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
1
1
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
This goes towards what I am aiming for. Will test it when I have time!
– geekoverdose
2 hours ago
1
1
@Rightleg True, but OP said
I would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.– ruohola
1 hour ago
@Rightleg True, but OP said
I would value being pythonic more than having the most optimized runtime., so I don't think he'll need to do this to a huge string.– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
@geekoverdose Added new solutions which answer your updated requirements :)
– ruohola
1 hour ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
You defaced your original answer which was actually great. Now both your solutions uselessly clug the memory, and are no longer readable.
– Right leg
34 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
@Rightleg Doesn't matter since the original answer was not working with the updated requirements so it was pretty much worthless. But I edited it back since you're right about it being so clean.
– ruohola
19 mins ago
add a comment |
This does not look Pythonic because it's not a one-liner, and it uses range(len(foo)), but it's pretty straightforward and probably not too inefficient.
def last_match(pattern, string):
for i in range(1, len(string) + 1):
substring = string[-i:]
if re.match(pattern, substring):
return len(string) - i
The idea is to iterate over the suffixes of string from the shortest to the longest, and to check if it matches pattern.
Since we're checking from the end, we know for sure that the first substring we meet that matches the pattern is the last.
2
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
This is not very readable, uses therange(len(foo))antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.
– ruohola
2 hours ago
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
|
show 3 more comments
This does not look Pythonic because it's not a one-liner, and it uses range(len(foo)), but it's pretty straightforward and probably not too inefficient.
def last_match(pattern, string):
for i in range(1, len(string) + 1):
substring = string[-i:]
if re.match(pattern, substring):
return len(string) - i
The idea is to iterate over the suffixes of string from the shortest to the longest, and to check if it matches pattern.
Since we're checking from the end, we know for sure that the first substring we meet that matches the pattern is the last.
2
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
This is not very readable, uses therange(len(foo))antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.
– ruohola
2 hours ago
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
|
show 3 more comments
This does not look Pythonic because it's not a one-liner, and it uses range(len(foo)), but it's pretty straightforward and probably not too inefficient.
def last_match(pattern, string):
for i in range(1, len(string) + 1):
substring = string[-i:]
if re.match(pattern, substring):
return len(string) - i
The idea is to iterate over the suffixes of string from the shortest to the longest, and to check if it matches pattern.
Since we're checking from the end, we know for sure that the first substring we meet that matches the pattern is the last.
This does not look Pythonic because it's not a one-liner, and it uses range(len(foo)), but it's pretty straightforward and probably not too inefficient.
def last_match(pattern, string):
for i in range(1, len(string) + 1):
substring = string[-i:]
if re.match(pattern, substring):
return len(string) - i
The idea is to iterate over the suffixes of string from the shortest to the longest, and to check if it matches pattern.
Since we're checking from the end, we know for sure that the first substring we meet that matches the pattern is the last.
answered 3 hours ago
Right legRight leg
8,70342450
8,70342450
2
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
This is not very readable, uses therange(len(foo))antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.
– ruohola
2 hours ago
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
|
show 3 more comments
2
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
This is not very readable, uses therange(len(foo))antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.
– ruohola
2 hours ago
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
2
2
This is just not pythonic at all.
– ruohola
2 hours ago
This is just not pythonic at all.
– ruohola
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
I've come up with something similar to this, but I am not satisfied with its structure. A pythonic one-liner that is easily understand- and maintainable would be preferred. If this really is one of the most pythonic ways to achieve my goal, then I feel like filing a bug report with Python for this.
– geekoverdose
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
@ruohola I'm interested to hear your criteria.
– Right leg
2 hours ago
1
1
This is not very readable, uses the
range(len(foo)) antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.– ruohola
2 hours ago
This is not very readable, uses the
range(len(foo)) antipattern, is quite a lot of lines etc. It's a valid solution, but when OP asked specifically for a 'pythonic' solution, I don't feel like this cuts it.– ruohola
2 hours ago
1
1
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
I think you guys are confusing what pythonic is. Zen of python: "Readability counts." A crunched one liner doesn't mean its pythonic.
– Julian Camilleri
2 hours ago
|
show 3 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55890245%2fpython-pythonic-way-to-find-last-position-in-string-that-does-not-match-regex%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
last position that does 'not' or does match regex? Last
ematches[^0-9]pattern.– dgumo
3 hours ago
Last position that does not match a certain pattern, like being a number. For numbers this would be
[^0-9]. I'll update the question.– geekoverdose
2 hours ago
Should
s = 'uiae1iuae200aaaaaaaa'return the index of last char before a digit akae(8) or the last char akaa(19)?– ruohola
2 hours ago
1
With
uiae1iuae200aaaaaaaait should return the last position in the string, means19.– geekoverdose
2 hours ago