我正在编写一个函数来替换字符串中的每个第n个字母
def replaceN(str, n):
for i in range(len(str)):
n=str[i]
newStr=str.replace(n, "*")
return newStr
但是当我执行它时,只有第一个字母被替换为*。我确定有一个错误,但我看不到它。
答案 0 :(得分:7)
一衬垫:
newstring = ''.join("*" if i % n == 0 else char for i, char in enumerate(string, 1))
展开:
def replace_n(string, n, first=0):
letters = (
# i % n == 0 means this letter should be replaced
"*" if i % n == 0 else char
# iterate index/value pairs
for i, char in enumerate(string, -first)
)
return ''.join(letters)
>>> replace_n("hello world", 4)
'*ell* wo*ld'
>>> replace_n("hello world", 4, first=-1)
'hel*o w*orl*'
答案 1 :(得分:2)
您的代码有几个问题:
首先,return
在错误的地方。它在for循环中,但它应该在外面。
接下来,在以下片段中:
for i in range(len(str)):
n=str[i]
newStr=str.replace(n, "*")
您作为函数的第二个参数传递的n
在每个循环步骤都被覆盖。因此,如果你的初始字符串是“abcabcabcd”并且你传递n = 3(一个数字)作为第二个参数,你的循环是做什么的:
n="a"
n="b"
n="c"
...
所以从不使用值3。此外,在您的循环中,只保存字符串中的最后一次替换:
n="a"
newStr="abcabcabcd".replace("a", "*") --> newStr = "*bc*bc*bcd"
n="b"
newStr="abcabcabcd".replace("b", "*") --> newStr = "a*ca*ca*cd"
...
n="d"
newStr="abcabcabcd".replace("d", "*") --> newStr = "abcabcabc*"
如果您使用某些字符串测试函数(在修复return
位置之后),它似乎工作正常:
In [7]: replaceN("abcabcabc", 3)
Out[7]: 'ab*ab*ab*'
但是如果你更仔细地做出选择:
In [10]: replaceN("abcabcabcd", 3)
Out[10]: 'abcabcabc*'
然后很明显代码失败了,它等同于只替换字符串的最后一个字符:
my_string.replace(my_string[-1], "*")
Eric提供的代码工作正常:
In [16]: ''.join("*" if i % 3 == 0 else char for i, char in enumerate("abcabcabcd"))
Out[16]: '*bc*bc*bc*'
取代第3,第6,第9等位置。如果您不希望更换位置0,则可能需要进行一些调整。
答案 2 :(得分:1)
试试这个:
public class BasicTreeGrid extends VerticalLayout {
// used to generate some random data
private final Random random = new Random();
public BasicTreeGrid() {
// basic tree setup
TreeGrid<Project> treeGrid = new TreeGrid<>();
addComponent(treeGrid);
treeGrid.addColumn(Project::getName).setCaption("Project Name").setId("name-column");
treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done");
treeGrid.addColumn(Project::getLastModified).setCaption("Last Modified");
// some listeners for interaction
treeGrid.addCollapseListener(event -> Notification
.show("Project '" + event.getCollapsedItem().getName() + "' collapsed.", Notification.Type.TRAY_NOTIFICATION));
treeGrid.addExpandListener(event -> Notification
.show("Project '" + event.getExpandedItem().getName() + "' expanded.", Notification.Type.TRAY_NOTIFICATION));
// add the list of root projects and specify a provider of sub-projects
treeGrid.setItems(generateProjectsForYears(2010, 2016), Project::getSubProjects);
}
// generate some random projects
private List<Project> generateProjectsForYears(int startYear, int endYear) {
List<Project> projects = new ArrayList<>();
for (int year = startYear; year <= endYear; year++) {
Project yearProject = new Project("Year " + year);
for (int i = 1; i < 2 + random.nextInt(5); i++) {
Project customerProject = new Project("Customer Project " + i);
customerProject.setSubProjects(Arrays.asList(
new LeafProject("Implementation", random.nextInt(100), year),
new LeafProject("Planning", random.nextInt(10), year),
new LeafProject("Prototyping", random.nextInt(20), year)));
yearProject.addSubProject(customerProject);
}
projects.add(yearProject);
}
return projects;
}
// basic parent (or intermediate child) bean used for easy binding
class Project {
private List<Project> subProjects = new ArrayList<>();
private String name;
public Project(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<Project> getSubProjects() {
return subProjects;
}
public void setSubProjects(List<Project> subProjects) {
this.subProjects = subProjects;
}
public void addSubProject(Project subProject) {
subProjects.add(subProject);
}
public int getHoursDone() {
return getSubProjects().stream().map(project -> project.getHoursDone()).reduce(0, Integer::sum);
}
public Date getLastModified() {
return getSubProjects().stream().map(project -> project.getLastModified()).max(Date::compareTo).orElse(null);
}
}
// basic final child (can not have other children) bean used for easy binding
class LeafProject extends Project {
private int hoursDone;
private Date lastModified;
public LeafProject(String name, int hoursDone, int year) {
super(name);
this.hoursDone = hoursDone;
lastModified = new Date(year - 1900, random.nextInt(12), random.nextInt(10));
}
@Override
public int getHoursDone() {
return hoursDone;
}
@Override
public Date getLastModified() {
return lastModified;
}
}
}
答案 3 :(得分:0)
你已经将你的返回放在循环中,所以在第一次迭代之后它返回字符串而不替换其余的字符串。一旦循环完成,就应该返回该字符串。这样的事情应该有效:
def replaceN(str, n):
for i in range(len(str)):
n=str[i]
newStr=str.replace(n, "*")
return newStr
答案 4 :(得分:0)
另一种选择,使用re:
import re
def repl(matchobj):
return re.sub('.$','*',matchobj.group(0))
def replaceN(str, n):
return re.sub('.'*n,repl,str)
但是,这需要额外的库。如果您已导入此库,则这可能是一种简写方法。
答案 5 :(得分:0)
我喜欢Eric的回答,但你在评论中表示不应该替换第一个字母。您可以像这样调整代码:
''.join("*" if i % n == 0 else char for i, char in enumerate(string, 1))
the difference is here ^
def replaceN(s, n):
return ''.join(
'*' if not i%n else char for i, char in enumerate(s, 1))
>>> replaceN('welcome', 3)
'we*co*e'
答案 6 :(得分:0)
每次重新定义字符串的简单方法:
def replaceN(string, n):
for i in range(n, len(string), n):
string = string[:i-1] + "*" + string[i:]
return string
In [1]: replaceN("abcabcabc", 3)
Out[1]: ab*ab*ab*
In [2]: replaceN("abcd abcd abcd", 4)
Out[2]: abcd*abcd*abcd