我有以下问题指出
用
+
符号替换字符串中的所有字符,方法中给定字符串的实例除外
例如,如果给定的字符串为abc123efg
,并且他们希望我替换除123
的每个实例之外的所有字符,则它将变为+++123+++
。
我认为正则表达式可能是最好的选择,我想到了这个。
str.replaceAll("[^str]","+")
其中str是一个变量,但是它不允许我在不使用引号的情况下使用该方法。如果我只想替换可变字符串str,该怎么办?我使用手动键入的字符串来运行它并且可以在该方法上使用,但是我可以只输入一个变量吗?
到目前为止,我相信它正在寻找字符串“ str”而不是变量字符串。
除了两个:(
未完成的测试用例列表:
plusOut("12xy34", "xy") → "++xy++"
plusOut("12xy34", "1") → "1+++++"
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"
plusOut("abXYabcXYZ", "ab") → "ab++ab++++"
plusOut("abXYabcXYZ", "abc") → "++++abc+++"
plusOut("abXYabcXYZ", "XY") → "++XY+++XY+"
plusOut("abXYxyzXYZ", "XYZ") → "+++++++XYZ"
plusOut("--++ab", "++") → "++++++"
plusOut("aaxxxxbb", "xx") → "++xxxx++"
plusOut("123123", "3") → "++3++3"
答案 0 :(得分:14)
看起来这是CodingBat上的plusOut
问题。
针对此问题,我有3种解决方案,并写了一个新的流媒体解决方案只是为了好玩。
从输入字符串中创建一个StringBuilder,然后在每个位置检查单词。如果不匹配,请替换字符,如果找到则跳过单词的长度。
public String plusOut(String str, String word) {
StringBuilder out = new StringBuilder(str);
for (int i = 0; i < out.length(); ) {
if (!str.startsWith(word, i))
out.setCharAt(i++, '+');
else
i += word.length();
}
return out.toString();
}
这可能是初学者程序员的预期答案,尽管假设该字符串不包含任何星体平面字符,该字符将由2个字符而不是1个字符表示。
public String plusOut(String str, String word) {
return str.replaceAll(java.util.regex.Pattern.quote(word), "@").replaceAll("[^@]", "+").replaceAll("@", word);
}
这不是一个适当的解决方案,因为它假定某个字符或字符序列未出现在字符串中。
请注意使用Pattern.quote
来防止word
方法将replaceAll
解释为正则表达式。
\G
的正则表达式public String plusOut(String str, String word) {
word = java.util.regex.Pattern.quote(word);
return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");
}
构造正则表达式\G((?:word)*+).
,它或多或少地执行解决方案1的工作:
\G
确保比赛从上一场比赛结束的地方开始((?:word)*+)
选取0个或多个word
实例-如果有的话,这样我们就可以用$1
替换它们。这里的关键是所有格量词*+
,它强制正则表达式保留找到的word
的任何实例。否则,当word
出现在字符串末尾时,正则表达式将无法正常工作,因为正则表达式会回退以匹配.
.
将不会成为任何word
的一部分,因为前一部分已经选择了word
的所有连续出现,并且不允许回溯。我们将其替换为+
public String plusOut(String str, String word) {
return String.join(word,
Arrays.stream(str.split(java.util.regex.Pattern.quote(word), -1))
.map((String s) -> s.replaceAll("(?s:.)", "+"))
.collect(Collectors.toList()));
}
这个想法是用word
分割字符串,其余部分进行替换,然后使用word
方法将它们与String.join
联接起来。
Pattern.quote
来避免split
将word
解释为正则表达式。由于默认情况下,split
会在数组末尾删除空字符串,因此我们需要在第二个参数中使用-1
来使split
保留这些空字符串。+
的字符串。在Java 11中,我们可以改用s -> String.repeat(s.length())
。答案 1 :(得分:6)
这比您最初想的要棘手,因为您不仅需要匹配字符,而且缺少特定的短语-否定的字符集不够。如果字符串是123,则需要:
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<div style="margin-bottom: 30px;">You have selected "{{ parentVar }}"</div>
<label>Test Autocomplete</label>
<autocomplete v-model="parentVar" :preset-val="parentVar" :items="autoOptions" />
</div>
<template id="autocomplete_template">
<div class="autocomplete">
<input type="text" @input="onChange" v-model="search" @keyup.down="onArrowDown" @keyup.up="onArrowUp" @keyup.enter="onEnter" class="form-control" />
<ul id="autocomplete-results" v-show="isOpen" class="autocomplete-results">
<li class="loading" v-if="isLoading">
Loading results...
</li>
<li v-else v-for="(result, i) in results" :key="i" @click="setResult(result)" class="autocomplete-result" :class="{ 'is-active': i === arrowCounter }">
{{ result }}
</li>
</ul>
</div>
</template>
https://regex101.com/r/EZWMqM/1/
即-在字符串或“ 123”的开头后面查找,确保当前位置后没有123,然后延迟重复任何字符,直到超前匹配“ 123”或字符串的末尾。这将匹配不在“ 123”子字符串中的所有字符。然后,您需要用(?<=^|123)(?!123).*?(?=123|$)
替换每个字符,然后可以使用+
和appendReplacement
创建结果字符串:
StringBuffer
输出:
String inputPhrase = "123";
String inputStr = "abc123efg123123hij";
StringBuffer resultString = new StringBuffer();
Pattern regex = Pattern.compile("(?<=^|" + inputPhrase + ")(?!" + inputPhrase + ").*?(?=" + inputPhrase + "|$)");
Matcher m = regex.matcher(inputStr);
while (m.find()) {
String replacement = m.group(0).replaceAll(".", "+");
m.appendReplacement(resultString, replacement);
}
m.appendTail(resultString);
System.out.println(resultString.toString());
请注意,如果+++123+++123123+++
在正则表达式中可以包含具有特殊含义的字符,则在连接到模式之前必须先对其进行转义。
答案 2 :(得分:2)
您可以一行完成:
input = input.replaceAll("((?:" + str + ")+)?(?!" + str + ").((?:" + str + ")+)?", "$1+$2");
这可以选择捕获每个字符的两侧的“ 123”并将其放回原位(如果没有“ 123”则为空白):
答案 3 :(得分:1)
因此,与其提供一个与缺少字符串匹配的正则表达式,不如说它是正则表达式。我们不妨只匹配所选的短语,然后在跳过的字符数后附加replies=[]
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
for full_tweets in tweepy.Cursor(api.user_timeline,screen_name='tartecosmetics',timeout=999999).items(10):
for tweet in tweepy.Cursor(api.search,q='to:'+'tartecosmetics',result_type='recent',timeout=999999).items(1000):
if hasattr(tweet, 'in_reply_to_status_id_str'):
if (tweet.in_reply_to_status_id_str==full_tweets.id_str):
replies.append(tweet.text)
print("Tweet :",full_tweets.text.translate(non_bmp_map))
for elements in replies:
print("Replies :",elements)
replies.clear()
。
+
答案 4 :(得分:1)
要完成这项工作,您需要使用图案的野兽。假设您以以下测试用例为例:
plusOut("abXYxyzXYZ", "XYZ") → "+++++++XYZ"
您需要做的是在模式中构建一系列子句以一次匹配一个字符:
[^XYZ]
X(?!YZ)
(?<!X)Y
Y(?!Z)
(?<!XY)Z
可以在以下位置找到此替换的示例:https://regex101.com/r/jK5wU3/4
这里是一个示例,说明了它可能如何工作(肯定没有优化,但是可以工作):
import java.util.regex.Pattern;
public class Test {
public static void plusOut(String text, String exclude) {
StringBuilder pattern = new StringBuilder("");
for (int i=0; i<exclude.length(); i++) {
Character target = exclude.charAt(i);
String prefix = (i > 0) ? exclude.substring(0, i) : "";
String postfix = (i < exclude.length() - 1) ? exclude.substring(i+1) : "";
// add the look-behind (?<!X)Y
if (!prefix.isEmpty()) {
pattern.append("(?<!").append(Pattern.quote(prefix)).append(")")
.append(Pattern.quote(target.toString())).append("|");
}
// add the look-ahead X(?!YZ)
if (!postfix.isEmpty()) {
pattern.append(Pattern.quote(target.toString()))
.append("(?!").append(Pattern.quote(postfix)).append(")|");
}
}
// add in the other character exclusion
pattern.append("[^" + Pattern.quote(exclude) + "]");
System.out.println(text.replaceAll(pattern.toString(), "+"));
}
public static void main(String [] args) {
plusOut("12xy34", "xy");
plusOut("12xy34", "1");
plusOut("12xy34xyabcxy", "xy");
plusOut("abXYabcXYZ", "ab");
plusOut("abXYabcXYZ", "abc");
plusOut("abXYabcXYZ", "XY");
plusOut("abXYxyzXYZ", "XYZ");
plusOut("--++ab", "++");
plusOut("aaxxxxbb", "xx");
plusOut("123123", "3");
}
}
更新:即使这样也不是很有效,因为它不能处理仅仅是重复字符(例如“ xx”)的排除项。正则表达式绝对不是正确的工具,但我认为这是可能的。闲逛后,我不确定是否存在可以使这项工作有效的模式。
答案 5 :(得分:1)
解决方案中的问题是您放置了一组实例字符串str.replaceAll("[^str]","+")
,它将排除变量str
中的任何字符,并且不能解决问题
EX :当您尝试str.replaceAll("[^XYZ]","+")
时,它将从替换方法中排除字符X
,字符Y
和字符Z
的任何组合因此您将获得“ ++XY+++XYZ
”。
实际上,您应该在str.replaceAll
中排除字符序列。
您可以通过使用{strong>捕获组这样的字符来实现,例如(XYZ)
,然后使用负向超前来匹配不包含字符序列的字符串:{ {1}}
请检查此solution,以获取有关此问题的更多信息,但您应该知道,找到正则表达式直接执行此操作可能会很复杂。
我找到了两个解决此问题的简单方法:
解决方案1 :
您可以实现一种方法,用给定字符串实例除外的所有字符替换为'^((?!XYZ).)*$
'
+
注意:String exWord = "XYZ";
String str = "abXYxyzXYZ";
for(int i = 0; i < str.length(); i++){
// exclude any instance string of exWord from replacing process in str
if(str.substring(i, str.length()).indexOf(exWord) + i == i){
i = i + exWord.length()-1;
}
else{
str = str.substring(0,i) + "+" + str.substring(i+1);//replace each character with '+' symbol
}
}
此if语句将从str.substring(i, str.length()).indexOf(exWord) + i
的替换过程中排除exWord
的任何实例字符串。
输出:
str
解决方案2 :
您可以使用 ReplaceAll 方法尝试这种方法,它不需要任何复杂的正则表达式:
+++++++XYZ
注意:仅当您的输入字符串String exWord = "XYZ";
String str = "abXYxyzXYZ";
str = str.replaceAll(exWord,"*"); // replace instance string with * symbol
str = str.replaceAll("[^*]","+"); // replace all characters with + symbol except *
str = str.replaceAll("\\*",exWord); // replace * symbol with instance string
不包含任何str
符号时,此解决方案才有效。
此外,您还应在短语实例字符串*
中的正则表达式中转义具有特殊含义的任何字符,例如:exWord
。