为了账号安全,请及时绑定邮箱和手机立即绑定

有没有更好的方法来插入“|” 转换成二进制字符串 rep 得到这个 10|000|001

有没有更好的方法来插入“|” 转换成二进制字符串 rep 得到这个 10|000|001

Go
凤凰求蛊 2022-01-10 17:44:20
"|"给定十进制的二进制字符串表示形式,是否有更好的方法插入字符串200 = 11001000 此函数返回字符串 =11|001|000虽然这个功能有效,但看起来很笨拙!!为什么在 GO 中做一个简单的字符插入这么难???func (i Binary) FString() string {    a := strconv.FormatUint(i.Get(), 2)    y := make([]string, len(a), len(a)*2)    data := []rune(a)    r := []rune{}    for i := len(data) - 1; i >= 0; i-- {        r = append(r, data[i])    }    for j := len(a) - 1; j >= 0; j-- {        y = append(y, string(r[j]))        if ((j)%3) == 0 && j > 0 {            y = append(y, "|")        }    }    return strings.Join(y, "")}
查看完整描述

3 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

取决于你叫什么更好。我会使用正则表达式。


在这种情况下,复杂性来自于从右侧插入分隔符。如果我们填充字符串使其长度是 3 的倍数,我们可以从左侧插入分隔符。我们可以很容易地使用正则表达式|在每三个字符之前插入。然后,我们可以去掉前导|+ 填充。


func (i Binary) FString() string {

    a := strconv.FormatUint(i.Get(), 2)

    pad_req := len(a) % 3

    padding := strings.Repeat("0", (3 - pad_req))

    a = padding + a

    re := regexp.MustCompile("([01]{3})")

    a = re.ReplaceAllString(a, "|$1")

    start := len(padding) + 1

    if len(padding) == 3 {

        // If we padded with "000", we want to remove the `|` before *and* after it

        start = 5

    }

    a = a[start:]

    return a

}


查看完整回答
反对 回复 2022-01-10
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

如果性能不重要并且您只想要一个紧凑的版本,您可以将输入数字复制到输出,并在将|一组 2 写入输出时插入一个符号。


组从右到左计数,因此当从左到右复制数字时,第一组可能更小。因此,组内的数字计数器不一定从0第一组的情况开始,而是从len(input)%3.


这是一个例子:


func Format(s string) string {

    b, count := &bytes.Buffer{}, len(s)%3

    for i, r := range s {

        if i > 0 && count == i%3 {

            b.WriteRune('|')

        }

        b.WriteRune(r)

    }

    return b.String()

}

测试它:


for i := uint64(0); i < 10; i++ {

    fmt.Println(Format(strconv.FormatUint(i, 2)))

}

fmt.Println(Format(strconv.FormatInt(1234, 2)))

输出(在Go Playground上试试):


0

1

10

11

100

101

110

111

1|000

1|001

10|011|010|010

如果您必须多次执行此操作并且性能确实很重要,请查看我对问题的回答:How to fmt.Printf an integer with many comma


基于此,一个快速的解决方案可以是:


func Format(s string) string {

    out := make([]byte, len(s)+(len(s)-1)/3)

    for i, j, k := len(s)-1, len(out)-1, 0; ; i, j = i-1, j-1 {

        out[j] = s[i]

        if i == 0 {

            return string(out)

        }

        if k++; k == 3 {

            j, k = j-1, 0

            out[j] = '|'

        }

    }

}

输出当然是一样的。在Go Playground上尝试一下。


查看完整回答
反对 回复 2022-01-10
?
函数式编程

TA贡献1807条经验 获得超9个赞

这是一个分区问题。您可以使用此功能:


func partition(s, separator string, pLen int) string {

    if pLen < 1 || len(s) == 0 || len(separator) == 0 {

        return s

    }


    buffer := []rune(s)

    L := len(buffer)

    pCount := L / pLen


    result := []string{}


    index := 0

    for ; index < pCount; index++ {

        _from := L - (index+1)*pLen

        _to := L - index*pLen

        result = append(result, string(buffer[_from:_to]))

    }


    if L%pLen != 0 {

        result = append(result, string(buffer[0:L-index*pLen]))

    }


    for h, t := 0, len(result)-1; h < t; h, t = h+1, t-1 {

        result[t], result[h] = result[h], result[t]

    }


    return strings.Join(result, separator)

}

并且s := partition("11001000", "|", 3)会给你11|001|000。


这是一个小测试:


func TestSmokeTest(t *testing.T) {

    input := "11001000"

    s := partition(input, "|", 3)

    if s != "11|001|000" {

        t.Fail()

    }

    s = partition(input, "|", 2)

    if s != "11|00|10|00" {

        t.Fail()

    }


    input = "0111001000"

    s = partition(input, "|", 3)

    if s != "0|111|001|000" {

        t.Fail()

    }

    s = partition(input, "|", 2)

    if s != "01|11|00|10|00" {

        t.Fail()

    }

}


查看完整回答
反对 回复 2022-01-10
  • 3 回答
  • 0 关注
  • 122 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信