如何移除字符串中的最后一个字符?

3

我需要移除字符串的最后一个字符,而在我的情况下这个字符是逗号(","):

foreach(line; fcontent.splitLines)
{
    string row = line.split.map!(a=>format("'%s', ", a)).join;
    writeln(row.chop.chop);
}

我只找到一种方法-调用两次chop函数。首先移除\r\n,然后再移除最后一个字符。
是否有更好的方法?

var newString = 字符串 - AJ_91
5个回答

4
import std.array;
if (!row.empty)
    row.popBack();

这是正确的答案。其他解决方案多么复杂,有点奇怪。 - Andrei Alexandrescu
小问题是在OP的情况下需要调用两次popBack(),每次首先检查row.empty()以确保正确性。这假设他的输入以\r\n结尾,因为这似乎是情况。 - David Eagen
你可以在不保留终止符的情况下拆分字符串。foreach(line, content.splitLines(keepTerminator.no)) { ... } - Panke

2

通常情况下,字符串处理取决于您对Unicode的关注程度。

如果您只使用ASCII,那么非常简单:

import std.encoding;
// no "nice" ASCII literals, D really encourages Unicode
auto str1 = cast(AsciiString) "abcde";
str1 = str1[0 .. $-1]; // get slice of everything but last byte
auto str2 = cast(AsciiString) "abcde\n\r";
str2 = str2[0 .. $-3]; // same principle

"last char"实际上指的是Unicode码位(http://unicode.org/glossary/#code_point),这有点复杂。简单的方法是依靠D自动解码和算法:

import std.range, std.stdio;
auto range = "кириллица".retro.drop(1).retro();
writeln(range);

这里的retro (http://dlang.org/phobos/std_range.html#.retro)是一个懒惰的反向迭代函数。它接受任何范围 (unicode字符串是有效范围),并返回一个包装器,能够以反向迭代方式遍历它。 drop (http://dlang.org/phobos/std_range.html#.drop) 只是弹出单个范围元素并忽略它。再次调用retro将反转迭代顺序回到正常状态,但现在已经删除了最后一个元素。
它与ASCII版本不同的原因在于Unicode的本质 (特别是D默认使用的UTF-8) - 它不允许随机访问任何代码点。实际上,您需要一个一个地解码它们才能得到任何所需的索引。幸运的是,D为您处理了所有解码工作,并将其隐藏在方便的范围接口背后。
对于那些想要更准确的Unicode操作的人,应该可以操作字形(http://unicode.org/glossary/#grapheme):
import std.range, std.uni, std.stdio;
auto range = "abcde".byGrapheme.retro.drop(1).retro();
writeln(range);

很遗憾,由于Phobos中的一个漏洞,似乎目前不支持这种特定模式。我已经就此问题创建了一个Issue:https://issues.dlang.org/show_bug.cgi?id=14394


如果只是一个逗号,你可以轻松地检查字节并以这种方式完成,从而节省大量的Unicode表和处理麻烦... - Adam D. Ruppe
是的,我甚至不确定DMD是否能够正确地优化所有范围实用程序以直接访问最后几个字节 - 但仍然不想建议在一般情况下不适合的解决方案 ;) - Mihails Strasuns

0

注意:我更新了我的答案,使其更加简洁,并且删除了'map!'中的lambda函数,因为它有点丑陋。

import std.algorithm, std.stdio;
import std.string;
void main(){
    string fcontent = "I am a test\nFile\nwith some,\nCommas here and\nthere,\n";
    auto data = fcontent
        .splitLines
        .map!(a => a.replaceLast(","))
        .join("\n");
    writefln("%s", data);
}

auto replaceLast(string line, string toReplace){
    auto o = line.lastIndexOf(toReplace);
    return o >= 0 ? line[0..o] : line; 
} 

0
module main;
import std.stdio : writeln;
import std.string : lineSplitter, join;
import std.algorithm : map, splitter, each;

enum fcontent = "some text\r\nnext line\r\n";

void main()
{
    fcontent.lineSplitter.map!(a=>a.splitter(' ')
        .map!(b=>"'" ~ b ~ "'")
        .join(", "))
        .each!writeln;
}

我认为问题是如何在字符串末尾删除","字符,如果最后一个字符是","? - Colin Grogan
我的代码做的和原始代码一样。但我无法从问题中判断作者想要什么。 - Kozzi11

-1

看一下,我使用这个扩展方法来替换任何最后一个字符或子字符串,例如:

string testStr = "Happy holiday!";<br>

Console.Write(testStr.ReplaceVeryLast("holiday!", "Easter!"));

public static class StringExtensions
{
    public static string ReplaceVeryLast(this string sStr, string sSearch, string sReplace = "")
    {
        int pos = 0;

        sStr = sStr.Trim();

        do
        {
            pos = sStr.LastIndexOf(sSearch, StringComparison.CurrentCultureIgnoreCase);
            if (pos >= 0 && pos + sSearch.Length == sStr.Length)
                sStr = sStr.Substring(0, pos) + sReplace;

        } while (pos == (sStr.Length - sSearch.Length + 1));

        return sStr;
    }
}

1
D语言中的这个基本思路也非常简单,我会使用 auto offset = str.lastIndexOf("thing-to-chop-off"); if(offset >= 0) str = str[0 .. offset]; - Adam D. Ruppe
只是如果你没有注意到:你的代码是C#。OP的代码是D。 - Claudio P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接