英文:
Using office 365, how can I replace diacritics with 'normal' letters with an efficient formula?
问题
I'll continue with the translation:
ôöǒŏōõǫőốồɵøṓṑṍȫỗṏǿȭǭỏȍȏơổọớờỡộởợóòôöõṕṗᵽƥʀŕṙřŗɍɽȑȓṛṟṝśṡŝšṥṧṣṩşṫťƭṭʈṱṯⱦţŧúùûüǔŭūũůųűʉǘǜṹṻủȕȗưụṳứừṷṵữửựúùûüṽṿẃẁẇŵẅẉẋẍýỳẏŷÿȳỹɏỷƴỵýźżẑžƶẓẕ")),1)),MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1)))
Please note that some special characters remain as-is in the translation for clarity.
英文:
I want to turn letters with diacritics into plain letters, so -
áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâ =a
ḃƀɓḅḇ =b
ćċĉčçȼḉƈɔ =c
ḋďḑđɗḍḓḏðɖ =d
I'm using office 365, but need to achieve this without addins or VBA, using a formula. A lambda function is fine.
There's a solution here but
- It's slow
- It's hard to read
- It needs a single string as the input - it won't work with (and produce) an array of words without the diacritics in
- If a diacritic happens not to be listed, it won't be 'caught'
Re 2. & 4. the formula just lists some diacritics to be replaced - looking at Excel's character codes, there's no obvious pattern that can be used. So that might be the only way to do it.
I need a solution which doesn't use addins or VBA. Designed for Excel 2019, the solution below doesn't take advantage of LAMDA functions, which I can use.
=CONCAT(IFERROR(IF(EXACT(UPPER(MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1)),MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1)),UPPER(MID(CONCATENATE("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbcccccccccddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffggggggggghhhhhhhhhiiiiiiiiiiiiiiiiiiiijjjkkkkkkkklllllllllllll","mmmnnnnnnnnnnnnooooooooooooooooooooooooooooooooooooooooopppprrrrrrrrrrrrsssssssssttttttttttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvwwwwwwxxyyyyyyyyyyyyzzzzzzz"),SEARCH(MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1),CONCATENATE("áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâḃƀɓḅḇćċĉčçȼḉƈɔḋďḑđɗḍḓḏðɖéèėêëěĕēẽęȩɇếềḗḕễḝẻȅȇểẹḙḛệéèêëḟƒǵġĝǧğḡģǥɠḣĥḧȟḩħḥḫⱨıíìïǐĭīĩįɨḯỉȉȋịḭíìïîȷĵǰḱǩķƙᶄḳḵⱪĺŀľɫⱡļƚłḷḽḻḹꝈ","ḿṁṃńǹṅňñņɲṇṋṉñŋóòȯôöǒŏōõǫőốồɵøṓṑṍȫỗṏǿȭǭỏȍȏơổọớờỡộởợóòôöõṕṗᵽƥʀŕṙřŗɍɽȑȓṛṟṝśṡŝšṥṧṣṩşṫťƭṭʈṱṯⱦţŧúùûüǔŭūũůųűʉǘǜṹṻủȕȗưụṳứừṷṵữửựúùûüṽṿẃẁẇŵẅẉẋẍýỳẏŷÿȳỹɏỷƴỵýźżẑžƶẓẕ")),1)),MID(CONCATENATE("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbcccccccccddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffggggggggghhhhhhhhhiiiiiiiiiiiiiiiiiiiijjjkkkkkkkklllllllllllll","mmmnnnnnnnnnnnnooooooooooooooooooooooooooooooooooooooooopppprrrrrrrrrrrrsssssssssttttttttttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvwwwwwwxxyyyyyyyyyyyyzzzzzzz"),FIND(MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1),CONCATENATE("áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâḃƀɓḅḇćċĉčçȼḉƈɔḋďḑđɗḍḓḏðɖéèėêëěĕēẽęȩɇếềḗḕễḝẻȅȇểẹḙḛệéèêëḟƒǵġĝǧğḡģǥɠḣĥḧȟḩħḥḫⱨıíìïǐĭīĩįɨḯỉȉȋịḭíìïîȷĵǰḱǩķƙᶄḳḵⱪĺŀľɫⱡļƚłḷḽḻḹꝈ","ḿṁṃńǹṅňñņɲṇṋṉñŋóòȯôöǒŏōõǫőốồɵøṓṑṍȫỗṏǿȭǭỏȍȏơổọớờỡộởợóòôöõṕṗᵽƥʀŕṙřŗɍɽȑȓṛṟṝśṡŝšṥṧṣṩşṫťƭṭʈṱṯⱦţŧúùûüǔŭūũůųűʉǘǜṹṻủȕȗưụṳứừṷṵữửựúùûüṽṿẃẁẇŵẅẉẋẍýỳẏŷÿȳỹɏỷƴỵýźżẑžƶẓẕ")),1)),MID(B1,ROW(A$1:INDEX(A:A,LEN(B1))),1)))
答案1
得分: 2
以下是一个递归的 LAMBDA
函数,适用于您的问题。您可以在“名称管理器”中定义它,或者使用高级公式环境插件(公式1):
CLEANCHARS = LAMBDA(txt, old, new, IF(old <>"",
CLEANCHARS(SUBSTITUTE(txt, LEFT(old), new), RIGHT(old, LEN(old)-1), new), txt))
现在可以用它来解决您的具体问题,例如:
=CLEANCHARS(A1, "áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâ", "a")
或者,如果您不想定义一个递归函数,可以使用 REDUCE
(公式2):
=LET(x, A1, CLEANCHARS, LAMBDA(txt, old, new,
REDUCE(txt, SEQUENCE(LEN(old)), LAMBDA(ac, i, SUBSTITUTE(ac, MID(old, i, 1), new)))),
CLEANCHARS(x, "áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâ", "a"))
注意:递归函数受到当前操作数堆栈限制的影响(请查看此链接以获取更多信息)。对于 CLEANCHARS
,最多可以进行256
次递归替换。如果您认为可能会达到这个限制,那么请使用公式2:
> 此外,请注意,Excel 中的当前操作数堆栈限制为 1,024。这应该与计算时间一起考虑,因为当前递归限制设置为1,024 除以(lambda 参数数目 + 1)。
现在您可以将其扩展到一般情况,通过一次调用将整个数组清理干净,无需拖动公式:
=LET(lk, A2:B3, BYROW(D2:D3, LAMBDA(x, REDUCE(x, SEQUENCE(ROWS(lk)), LAMBDA(ac, i,
CLEANCHARS(ac, INDEX(lk, i, 1), INDEX(lk, i, 2)))))))
注意:以类似的方式可以调整为使用非递归方法(公式2)。
英文:
Here is a recursive LAMBDA
function that works for your problem. You can define it in the Name Manager for example, or use Advanced Formula Environment Add-ins (formula 1):
CLEANCHARS = LAMBDA(txt,old,new, IF(old <>"",
CLEANCHARS(SUBSTITUTE(txt,LEFT(old),new),RIGHT(old,LEN(old)-1),new),txt))
Now use it for your specific case, for example:
=CLEANCHARS(A1,"áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâ","a")
or you can use REDUCE
if you don't want to define a recursive function (formula 2):
=LET(x,A1, CLEANCHARS, LAMBDA(txt,old,new,
REDUCE(txt,SEQUENCE(LEN(old)),LAMBDA(ac,i,SUBSTITUTE(ac, MID(old,i,1),new)))),
CLEANCHARS(x, "áàȧäǎāãåąⱥấầắằǡǻǟẫẵảȁȃẩẳạḁậặăâ", "a"))
Note: Recursive functions are affected by current operand stack limit (check this link for more info). For CLEANCHARS
would be 256
recursive replacements. If you consider you can reach it, then use formula 2:
> ...Furthermore, do note that the current operand stack limit in Excel is 1,024. This should be borne in mind together with calculation times, as the current recursion limit is set as 1,024 divided by (number of lambda parameters + 1).
Here is the output (for recurse approach):
Now you can extend it for the general case, by doing all the clean up for an entire array. It spills out the entire array in just one call, no need to drag the formula down:
=LET(lk, A2:B3, BYROW(D2:D3, LAMBDA(x,REDUCE(x, SEQUENCE(ROWS(lk)),LAMBDA(ac,i,
CLEANCHARS(ac, INDEX(lk,i,1), INDEX(lk,i,2)))))))
Note: In a similar way it can be addapted for using the non-recursive approach (formula 2).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论