2016-05-30 2 views
13

В основном у меня есть []int{1, 2, 3}, я хочу, чтобы однострочный перевод был преобразован в строку «1, 2, 3» (мне нужно, чтобы разделитель был обычным, иногда ., иногда , и т. Д.). Ниже приводится лучшее, что я мог бы придумать. Поиск в Интернете и, похоже, не нашел лучшего ответа.One-liner to transform [] int в строку

В большинстве языков есть встроенные поддержки для этого, например:

питон:

> A = [1, 2, 3] 
> ", ".join([str(a) for a in A]) 
'1, 2, 3' 

идет:

package main 

import (
    "bytes" 
    "fmt" 
    "strconv" 
) 

// Could not find a one-liner that does this :(. 
func arrayToString(A []int, delim string) string { 

    var buffer bytes.Buffer 
    for i := 0; i < len(A); i++ { 
     buffer.WriteString(strconv.Itoa(A[i])) 
     if i != len(A)-1 { 
      buffer.WriteString(delim) 
     } 
    } 

    return buffer.String() 
} 

func main() { 
    A := []int{1, 2, 3} 
    fmt.Println(arrayToString(A, ", ")) 
} 

Конечно, должно быть утилита погружена в ход, что позволяет мне делать это с помощью одного лайнера?

Я знаю, что есть strings.Join(A, ", "), но это работает только если A уже [] строка.

+3

Там нет «я хочу» в Go. – Volker

+1

Ухаживать за разработкой? – N0thing

+2

"Я хочу сделать это {без цикла, в одной строке, не используя срез, с этим расположением файловой системы, что угодно}". как-то «не-Go-ish», поскольку Go сильно упрямый и полная противоположность «умному». Вы должны обработать несколько вещей: Напишите цикл. Вы хотите выполнить что-то трудное: Напишите несколько строк кода. Вы хотите использовать инструмент go: придерживайтесь условных обозначений рабочей области. – Volker

ответ

36

Для преобразования
A := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

в одну строку с разделителями строки, как
"1,2,3,4,5,6,7,8,9"
Использование:

strings.Trim(strings.Join(strings.Fields(fmt.Sprint(A)), delim), "[]") 

или:

strings.Trim(strings.Join(strings.Split(fmt.Sprint(A), " "), delim), "[]") 

или :

strings.Trim(strings.Replace(fmt.Sprint(A), " ", delim, -1), "[]") 

и вернуть его из функции, например, как в этом примере:

package main 

import "fmt" 
import "strings" 

func arrayToString(a []int, delim string) string { 
    return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]") 
    //return strings.Trim(strings.Join(strings.Split(fmt.Sprint(a), " "), delim), "[]") 
    //return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(a)), delim), "[]") 
} 

func main() { 
    A := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 

    fmt.Println(arrayToString(A, ",")) //1,2,3,4,5,6,7,8,9 
} 

Чтобы включить пробел после запятой, вы можете позвонить arrayToString(A, ", ") или, наоборот, определить возврат как return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim + " ", -1), "[]"), чтобы заставить его вставить после разделителя.

+1

Хотя они «умны», они гораздо менее эффективны, чем просто использование цикла. Вот почему Go препятствует созданию таких конструкций. – Flimzy

+0

Как полный Go noob, мне кажется странным, что программисты Go прибегают к таким трюкам, как в первую очередь. Похоже на прошлые дни для большинства других языков. –

+0

Хорошая регрессия действительно из чистого и простого '' 'a.implode (',')' '': - / –

2

Я считаю, что вы можете пойти с семейством функций fmt.Sprint. Я не эксперт в области гоу флагов форматирования, и, возможно, вы можете сделать это с только Sprintf, но вот один вкладыш, который работает:

data := []int{1,2,3} 

func(x string) string { return x[6:len(x)-1]; }(fmt.Sprintf("%#v", data)) // 1, 2, 3 

В общем, можно использовать strings.Replace придумать различные разделители (до тех пор, как вы можете спокойно заменить разделитель на , или по умолчанию):

// Produces 1--2--3 
magic := func(s, d string) string { return strings.Replace(s[1:len(s)-1], " ", d, -1) } 
fmt.Println(magic(fmt.Sprint([]int{1, 2, 3}), "--")) 

// As one liner 
fmt.Println(func(s, d string) string { return strings.Replace(s[1:len(s)-1], " ", d, -1) }(fmt.Sprint([]int{1, 2, 3}), "--")) 
+0

fmt.Println (fmt.Sprint (A)) дает '[1 2 3]' Это не позволяет использовать специальный разделитель ... – N0thing

+0

Точно. Вам нужно точно указать строку «1, 2, 3»? – AkiRoss

+0

Да, делая утверждение вопроса более очевидным, что мне нужно контролировать, что находится между цифрами. – N0thing

4

Я только что столкнулся с такой же проблемой сегодня, так как я ничего на стандартной библиотеке не найден, я перекомпилировать 3 способа сделать это преобразование

Создать строку и добавления значения из массива путем преобразования его с помощью strconv.Itoa:

func IntToString1() string { 
    a := []int{1, 2, 3, 4, 5} 
    b := "" 
    for _, v := range a { 
     if len(b) > 0 { 
      b += "," 
     } 
     b += strconv.Itoa(v) 
    } 

    return b 
} 

Создание строки [], преобразовать каждое значение массива, а затем возвращает на объединенную строку из [] строки:

func IntToString2() string { 
    a := []int{1, 2, 3, 4, 5} 
    b := make([]string, len(a)) 
    for i, v := range a { 
     b[i] = strconv.Itoa(v) 
    } 

    return strings.Join(b, ",") 
} 

Преобразовать [] INT в строку и заменить/обрезать значение:

func IntToString3() string { 
    a := []int{1, 2, 3, 4, 5} 
    return strings.Trim(strings.Replace(fmt.Sprint(a), " ", ",", -1), "[]") 
} 

Производительность довольно сильно отличается в зависимости от реализации:

BenchmarkIntToString1-12   3000000   539 ns/op 
BenchmarkIntToString2-12   5000000   359 ns/op 
BenchmarkIntToString3-12   1000000   1162 ns/op 

Лично я пойду с IntToString2, так что последняя функция может быть пакет Util в моем проекте, как это:

func SplitToString(a []int, sep string) string { 
    if len(a) == 0 { 
     return "" 
    } 

    b := make([]string, len(a)) 
    for i, v := range a { 
     b[i] = strconv.Itoa(v) 
    } 
    return strings.Join(b, sep) 
}