在Python中格式化一个字符串,使其具有与另一个字符串相同的空格。

huangapple go评论68阅读模式
英文:

Format a string to have the same spaces as another string in python

问题

如果我有两个相同长度的字符串

```python
foo = "foofoo foo fo o"
abc = "abcabcabcabc"

我想要能够做到这样:

func(abc,foo)
> "abcabc abc ab c"

我知道我可以通过检查第一个字符串中的空格位置,并在另一个字符串中相同的位置插入空格(考虑到之前添加的空格)来实现这一点,但是否有更直接和高效的方法?


<details>
<summary>英文:</summary>

If I have two strings of same length :

foo = "foofoo foo fo o"
abc = "abcabcabcabc"


I would like to be able to have something like this

func(abc,foo)
> "abcabc abc ab c"



I know I might be able to do this by checking where the spaces are in the first string and insert spaces at the same place in the other (taking into account the previously added ones), but is there something more direct and efficient ?

</details>


# 答案1
**得分**: 0

不要试图通过改变字符串来实现这个,我建议通过同时迭代两个字符串并构建一个新字符串来实现:

```python
>>> def func(a, b):
...     j = 0
...     ret = ""
...     for x in a:
...         if x.isspace():
...             ret += x
...         else:
...             ret += b[j]
...             j += 1
...     return ret
...
>>> func("foofoo foo fo o", "abcabcabcabc")
'abcabc abc ab c'
英文:

Rather than trying to do this by mutating the string, I'd suggest doing it by iterating over both strings in parallel and building a new string:

&gt;&gt;&gt; def func(a, b):
...     j = 0
...     ret = &quot;&quot;
...     for x in a:
...         if x.isspace():
...             ret += x
...         else:
...             ret += b[j]
...             j += 1
...     return ret
...
&gt;&gt;&gt; func(&quot;foofoo foo fo o&quot;, &quot;abcabcabcabc&quot;)
&#39;abcabc abc ab c&#39;

答案2

得分: 0

这里是代码的翻译部分:

foo = "foofoo foo fo o"
abc = "abcabcabcabc"

def manip(origin: str, pattern: str) -> str:
    comp: str = ""
    i: int = 0
    for p in pattern:
        comp += " " if p == " " else origin[i]
        if p != " ": i += 1
    return comp

print(manip(abc, foo))

请注意,我只翻译了代码部分,其他内容保持不变。

英文:

Maybe something like this:

foo = &quot;foofoo foo fo o&quot;
abc = &quot;abcabcabcabc&quot;

def manip(origin: str, pattern: str) -&gt; str:
	comp: str = &quot;&quot;
	i: int = 0
	for p in pattern:
		comp += &quot; &quot; if p == &quot; &quot;	else origin[i]
		if p != &quot; &quot;: i += 1
	return comp

print(manip(abc,foo))

答案3

得分: 0

def match_spaces(s1, s2):
    it = iter(s2)
    return ' '.join(l if l.isspace() else next(it) for l in s1)
    
match_spaces(foo, abc)
# 'a b c a b c   a b c   a b   c'
英文:

You could make an iterator out of the second string and yield values where s1 is not a space otherwise the next letter:

foo = &quot;foofoo foo fo o&quot;
abc = &quot;abcabcabcabc&quot;


def match_spaces(s1, s2):
    it = iter(s2)
    return &#39; &#39;.join(l if l.isspace() else next(it) for l in s1)

match_spaces(foo, abc)
# &#39;a b c a b c   a b c   a b   c&#39;

答案4

得分: 0

你可以使用 re.finditer() 来查找空格的位置,然后从这些索引构建字符串:

import re
from itertools import tee

foo = "foofoo foo fo o"
abc = "abcdefghijkl"

spans = []
pos = 0

a_start, a_end = (0, 0)
for m in re.finditer(" ", foo): 
    b_start, b_end = m.span()
    spans.append(abc[pos:pos + b_start - a_end])
    spans.append(m.group())
    pos += b_start - a_end
    a_start, a_end = b_start, b_end
    
spans.append(abc[pos:])
print("".join(spans))

或者,如果你可以将分割模式表示为负正则表达式,你可以使用 itertools 来优雅地表达它:

import re
from itertools import chain, tee, accumulate, pairwise

foo = "foofoo foo fo o"
abc = "abcdefghijkl"

matches = list(re.finditer("[^ ]+", foo))
lens = (m.end() - m.start() for m in matches)
accs = accumulate(lens, initial=0)
indices = pairwise(accs)
result = " ".join([abc[a:z] for m, (a, z) in zip(matches, indices)])
print(result)

pairwise 在 Python 3.10 及以上版本可用,accumulate 自 Python 3.2 可用,但 initial 参数是 Python 3.8 中新增的。有关适用于旧版本 Python 的等效实现,请参阅 itertools 文档。

英文:

You can use re.finditer() to find the position of spaces, and then just build the string from the indices:

import re
from itertools import tee

foo = &quot;foofoo foo fo o&quot;
abc = &quot;abcdefghijkl&quot;

spans = []
pos = 0

a_start, a_end = (0, 0)
for m in re.finditer(&quot; &quot;, foo): 
    b_start, b_end = m.span()
    spans.append(abc[pos:pos + b_start - a_end])
    spans.append(m.group())
    pos += b_start - a_end
    a_start, a_end = b_start, b_end
    
spans.append(abc[pos:])
print(&quot;&quot;.join(spans))

Alternatively, if you can express the split pattern as a negative regex, you can express this very elegantly using itertools instead:

import re
from itertools import chain, tee, accumulate, pairwise

foo = &quot;foofoo foo fo o&quot;
abc = &quot;abcdefghijkl&quot;

matches = list(re.finditer(&quot;[^ ]+&quot;, foo))
lens = (m.end() - m.start() for m in matches)
accs = accumulate(lens, initial=0)
indices = pairwise(accs)
result = &quot; &quot;.join([abc[a:z] for m, (a, z) in zip(matches, indices)])
print(result)

pairwise is available on Python 3.10 upwards, accumulate is available since Python 3.2, but the initial argument is new in Python 3.8. Refer to itertools documentations for equivalent implementation suitable for older Python.

huangapple
  • 本文由 发表于 2023年6月19日 10:44:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定