我想用library(tidyverse)
df %>%
group_by(col.1) %>%
filter(col.2 == 'b'| col.3 == 'c') %>%
ungroup %>%
filter(!duplicated(.[-1], fromLast = TRUE))
# A tibble: 3 x 3
# col.1 col.2 col.3
# <dbl> <fct> <fct>
#1 1 b c
#2 2 b a
#3 3 a c
类扫描字符串,并且我想将每个“ is”单词替换为“ is not”,期望嵌入“ is”例如“ this”
Scanner
成为good morning this is my name
我写代码段
good morning this is not my name
当我执行此程序时,它会打印:
public static void main(String[] args) {
String chaine="good morning this is my name";
Scanner sc=new Scanner(chaine);
while(sc.hasNext()) {
String word=sc.next();
if(word.equals("is"))
chaine=chaine.replace(word, "is not");
}
System.out.println(chaine);
}
,但我想打印早安good morning this not is not my name
答案 0 :(得分:1)
很抱歉,我没有看到您真正想要的是什么。我修改了一点您的代码。我使用StringBuilder存储单词的各个部分,然后关闭扫描仪。
public static void main(String[] args) {
String chaine="good morning this is my name";
Scanner sc=new Scanner(chaine);
StringBuilder sb = new StringBuilder();
while(sc.hasNext()) {
String word=sc.next();
if(word.equals("is"))
{
sb.append("is not");
}
else
{
sb.append(word);
}
//Add space after every added word.
sb.append(" ");
}
sc.close();
String result = sb.toString();
//Call trim to remove the space after the last word
System.out.println(result.trim());
}
祝大家好运!
答案 1 :(得分:1)
我已为您的问题附上了解决方案。这是与已提交解决方案更正的类似方法。考虑用例,用户将键入“早上好,这不是我的名字”。在这种情况下,代码也将“ is”替换为“ is not”。输出将是“早上好,这不是我的名字”。您可以考虑此解决方案,在这里我们可以检查它是否已经“不是”。
(我在这里假设您只是想将“ is”更正为“ is not”,如果用户键入“ is not”,那么您将不会进行任何更改。如果您要这样做,那么这里是正确的代码。 )
StringBuilder sb=new StringBuilder();
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {
String word=sc.nextLine();
if(!word.contains("is not"))
sb.append(word.replace("is","is not"));
else sb.append(word);
sb.append("\n"); //new line to get same string as
// user's input
}
sc.close();
System.out.println(sb.toString());
如果要使用较早的解决方案,则必须设置条件以检查用户是否已经提供了正确的输入。
答案 2 :(得分:0)
您可以使用replace
方法替换子字符串。
但是无论如何,如果您不需要替换其他单词,只需将" is "
括在方括号中即可。
答案 3 :(得分:0)
这有效
if(word.equals("is")) {
chaine=chaine.replaceFirst(" "+word+" ", " is not ");
}
replace函数将替换您给出的单词的所有出现,并且您将其赋予的“ is”包含在“ this”中,只是在其中添加一些空格以防止出现这种情况。首先使用替换将替换第一次出现的内容,而不是使用替换将替换所有内容。
即使使用Scanner,自已也不是正确的做法
答案 4 :(得分:0)
由于您使用的是Java的Scanner类,并且将Scanner#next()方法与Scanner#hasNext()方法结合使用,因此您可以期望检索字符串中的每个单词作为每次迭代的标记同时循环。
当您专门使用String#replace()方法时,这是一种更好的机制(使用扫描仪),因为Scanner#next()方法根据默认的空白自行检索每个单词定界符(因为您尚未使用Scanner#useDelimiter()方法指定定界符-请注意:稍后更多)。
您可能已经知道String#replace()方法将替换字符串中某个字符串的所有出现位置,无论是在单词内还是在单词本身内,因此您不想播放它这种特殊情况下的名片。
您的问题是您针对{strong> entire 字符串使用了String#replace()方法,而不仅仅是找到的单词本身:
if(word.equals("is")) {
chaine = chaine.replace(word, "is not");
}
这当然会替换整个字符串中所有出现的子字符串is
(显然不希望包含单词“ th is ”。应该是:>
if(word.equals("is")) {
word = word.replace(word, "is not");
}
,然后将 word 变量的内容附加到特定的字符串构建中。在完成 while 循环的每次迭代时,您需要重建字符串,以完成对Scanner#next()方法检索到的每个单词的处理。
对于这种小用例,可以使用String Concatenation Operator (+)来重建字符串:
String finalString = ""; // Will hold the string build
while (sc.hasNext()) {
String word = sc.next();
if (word.equals("is")) {
word = word.replace(word, "is not");
}
// Rebuild the string upon each iteration
finalString+= (!finalString.equals("") ? " " + word : word);
}
在上面的代码行:finalString+= (finalString.equals("") ? word : " " + word);
中,您可以看到字符串连接运算符( + )的使用:finalString+=
,但后面还有一个等号字符。这基本上是告诉编译器 finalyString 是要保存和维护其中已经包含的字符串数据,换句话说:finalyString = finallyString +
。
在上面的代码行中,您还可以看到使用Ternary Operator以便在需要的地方应用空格:
(finalString+= (!finalString.equals("") ? " " + word : word);
三元运算符的工作方式与 if / else 情形非常相似。使用 if / else ,它看起来像:
// If finalString is NOT empty
if (!finalString.equals("") {
// Append a white-space and then the word
finalString+= " " + word;
}
// otherwise if finalString is empty
else {
// Just append the word
finalString+= word;
}
您可以快速了解为什么使用三元运算符是一个好方法。
重建字符串的另一种方法是利用StringBuilder类。最好使用此类通过大量迭代来构建大量字符串。即使在这样的小情况下,也要养成使用此类的习惯:
String chaine = "good morning this is my name";
Scanner sc = new Scanner(chaine);
StringBuilder sb = new StringBuilder();
while (sc.hasNext()) {
String word = sc.next();
if (word.equals("is")) {
word = word.replace(word, "is not");
}
/* If the 'string build' is not empty then add
a white-space in preperation for next word. */
if (!sb.toString().equals("")) {
sb.append(" ");
}
// Append next word (modified or not)
sb.append(word);
}
chaine = sb.toString();
这一切都很好,但所有这些都存在一个小问题。如果提供的主字符串在我们希望保留的字符串的特定位置带有填充或其他空格怎么办?上面的构建示例将其删除。
在检索每个标记(单词)时,带有Scanner#hasNext()的Scanner#next()会忽略所有空格。在许多情况下,这实际上可能是一个主要问题,但是由于有一个简单的解决方法,并不是所有的问题都会丢失。
还记得我们之前提到的Scanner#useDelimiter()方法吗?好吧,用它:
Scanner sc = new Scanner(chaine).useDelimiter(" ");
现在空白将不被忽略,并以Null字符串(“” )的形式检索,并在我们的代码中通过以下方式处理:
// In the String Concatenation Operator code
finalString+= (!finalString.equals("") ? " " + word : word);
O R
// In the StringBuilder code
if (!sb.toString().equals("")) {
sb.append(" ");
}
但是,这并不能解决主字符串中的 Leading 空格。为了照顾 Leading 空格,我们需要添加一些其他代码:
// In the String Concatenation Operator code
finalString+= (!finalString.equals("") || word.equals("") ? " " + word : word);
O R
// In the StringBuilder code
if (!sb.toString().equals("") || word.equals("")) {
sb.append(" ");
}
完成了...。但是,您知道,您可以使用String#replaceAll()方法通过一行代码来完成同一件事:
String chaine = "good morning this is my name";
// A Single line of code (all whitespaces remain intact).
chaine = chaine.replaceAll("\\bis\\b", "is not");
String#replaceAll()方法允许使用Regular Expressions( RegEx )可以使很多情况下的生活变得更加轻松。
传递给上述 replaceAll()方法的正则表达式("\\bis\\b"
)包含Word Boundary元字符 \ b ,该字符可检查字符串还是子字符串模式在单词边界处开始和结束,表达式中的单词当然是“ 是”。您可以在此处阅读有关Boundary Matchers的信息。如果您想使用正则表达式并对其进行测试,则可以在RegEx101.com进行。