Selectively replace multiple instances of a character within a string: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Added a version in Haskell)
(→‎Python: Added a further variant ( a map-accumulation ))
Line 512: Line 512:
],
],
)
)
)</lang>
)
</lang>

{{out}}
{{out}}
<pre>
<pre>AErBcadCbFD</pre>

AErBcadCbFD

</pre>
Or, as a map-accumulation:
<lang python>from functools import reduce


# nthInstanceReplaced :: Dict Char [(None | Char)] ->
# String -> String
def nthInstanceReplaced(ruleMap):
def go(a, c):
i = a.get(c, 0)
deltas = ruleMap.get(c, [])
return (
dict(a, **{c: 1 + i}),
deltas[i] or c if i < len(deltas) else c
)

return lambda s: ''.join(
mapAccumL(go)({})(s)[1]
)


# ------------------------- TEST -------------------------
def main():
'''Rule-set applied to a given string.'''

print(
nthInstanceReplaced({
'a': ['A', 'B', None, 'C', 'D'],
'b': ['E'],
'r': [None, 'F']
})(
"abracadabra"
)
)


# ----------------------- GENERIC ------------------------

# mapAccumL :: (acc -> x -> (acc, y)) ->
# acc -> [x] -> (acc, [y])
def mapAccumL(f):
'''A tuple of an accumulation and a map
with accumulation from left to right.
'''
def go(a, x):
return second(lambda v: a[1] + [v])(
f(a[0], x)
)
return lambda acc: lambda xs: reduce(
go, xs, (acc, [])
)


# second :: (a -> b) -> ((c, a) -> (c, b))
def second(f):
'''A simple function lifted to a function over a tuple,
with f applied only to the second of two values.
'''
return lambda xy: (xy[0], f(xy[1]))


# MAIN ---
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>AErBcadCbFD</pre>


=={{header|Raku}}==
=={{header|Raku}}==