替换字符串中的每个第n个字母

时间:2012-12-02 11:27:47

标签: python replace

我正在编写一个函数来替换字符串中的每个第n个字母

def replaceN(str, n):
   for i in range(len(str)):
     n=str[i]
     newStr=str.replace(n, "*")
     return newStr

但是当我执行它时,只有第一个字母被替换为*。我确定有一个错误,但我看不到它。

7 个答案:

答案 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