D:如何删除字符串中的最后一个字符?

时间:2015-04-02 12:40:37

标签: string d

我需要删除字符串中的最后一个字符串,例如它的逗号(","):

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

我发现只有一种方法 - 两次叫剁。首先删除\r\n,然后删除最后一个字符。

有没有更好的方法?

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

正如字符串处理通常会发生的那样,它取决于你关心多少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

In" last char"实际上意味着unicode代码点(http://unicode.org/glossary/#code_point)它变得有点复杂。简单的方法就是依靠D自动解码和算法:

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

这里retrohttp://dlang.org/phobos/std_range.html#.retro)是一个惰性反向迭代函数。它需要任何范围(unicode字符串是有效范围)并返回能够向后迭代它的包装器。

drophttp://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中的错误,看起来这个特定的模式并没有得到支持。我创建了一个关于它的问题:https://issues.dlang.org/show_bug.cgi?id=14394

答案 2 :(得分:0)

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

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;
    }
}

答案 3 :(得分: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; 
} 

答案 4 :(得分: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;
}