2016-05-30 17 views
13

Fondamentalmente ho []int{1, 2, 3}, voglio un one-liner che lo trasforma nella stringa "1, 2, 3" (ho bisogno del delimitatore per essere personalizzato, a volte ., a volte ,, ecc.). Di seguito è il meglio che potrei venire con. Ho cercato online e non sembrava trovare una risposta migliore.One-liner da trasformare [] int nella stringa

Nella maggior parte delle lingue c'è il supporto in-built per questo, ad esempio:

pitone:

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

Go:

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, ", ")) 
} 

Sicuramente ci deve essere un programma di utilità sepolto in movimento che mi permette di fare questo con un one-liner?

So che c'è strings.Join(A, ", "), ma funziona solo se A è già [] stringa.

+3

Non c'è un "io voglio" in Go. – Volker

+1

Cura di elaborare? – N0thing

+2

"Voglio fare questo {senza un loop, in una riga, non usando una slice, con questo layout di filesystem, qualunque sia}." è in qualche modo "non-Go-ish" come Go è fortemente supponente e l'esatto opposto di "intelligente". Devi elaborare diverse cose: Scrivi un ciclo. Vuoi realizzare qualcosa di difficile: scrivi diverse righe di codice. Si desidera utilizzare lo strumento Vai: attenersi alle convenzioni dell'area di lavoro. – Volker

risposta

36

Per convertire
A := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

ad una stringa delimitata una riga come
"1,2,3,4,5,6,7,8,9"
uso:

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

o:

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

o :

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

e ritorno da una funzione come in questo esempio:

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 
} 

Per includere uno spazio dopo la virgola, è possibile chiamare arrayToString(A, ", ") o viceversa definire il reso come return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim + " ", -1), "[]") per forzare l'inserimento dopo il delimitatore.

+1

Sebbene siano "intelligenti", sono molto meno efficienti di un semplice loop. Ecco perché Go scoraggia costrutti come questi. – Flimzy

+0

Come completo Go noob mi sembra strano che i programmatori Go ricorrere a trucchi del genere in primo luogo. Sembra che siano passati giorni per la maggior parte delle altre lingue. –

+0

Bella regressione in effetti da un semplice e pulito '' 'a.implode (',')' '': - / –

2

Credo che si possa andare con la famiglia di funzioni fmt.Sprint. Io non sono esperto di bandiere di formattazione andare, e forse si può fare con un semplice Sprintf, ma ecco una battuta che funziona:

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

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

In generale, è possibile utilizzare strings.Replace a venire con diversi separatori (fino a quando si può tranquillamente sostituire il separatore , o predefinito):

// 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)) restituisce '[1 2 3]' Ciò non consente un delimitatore personalizzato ... – N0thing

+0

Precisamente. Ti serve * esattamente * la stringa "1, 2, 3"? – AkiRoss

+0

Sì, rendendo l'affermazione della domanda un po 'più ovvia che ho bisogno di controllare cosa c'è tra i numeri. – N0thing

4

Ho appena incontrato lo stesso problema di oggi, dal momento che non ho trovato nulla su libreria standard, ho ricompilato 3 modi per fare questa conversione

creare una stringa e aggiungendo i valori dalla matrice convertendolo usando 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 
} 

creare una stringa [], convertire ogni valore di matrice e quindi restituire una stringa uniti da [] stringa:

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, ",") 
} 

Convertire il [] int in una stringa e sostituire/tagliare il valore:

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

prestazioni è molto diversa a seconda realizzazione:

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

Personalmente, io andrò con IntToString2, quindi la funzione finale potrebbe essere un pacchetto util nel mio progetto come questo:

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