Como concatenar seqüências de caracteres?

199

Como concatenar as seguintes combinações de tipos:

  • str e str
  • String e str
  • String e String
jsalter
fonte
14
Observe que stre &strsão tipos diferentes e, por 99% do tempo, você só deve se preocupar &str. Há outras perguntas detalhando as diferenças entre eles.
Shepmaster # 10/15

Respostas:

235

Ao concatenar cadeias, você precisa alocar memória para armazenar o resultado. O mais fácil de começar é Stringe &str:

fn main() {
    let mut owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    owned_string.push_str(borrowed_string);
    println!("{}", owned_string);
}

Aqui, temos uma string de propriedade que podemos mudar. Isso é eficiente, pois potencialmente nos permite reutilizar a alocação de memória. Há um caso semelhante para Stringe String, como &String pode ser desreferenciado como&str .

fn main() {
    let mut owned_string: String = "hello ".to_owned();
    let another_owned_string: String = "world".to_owned();

    owned_string.push_str(&another_owned_string);
    println!("{}", owned_string);
}

Depois disso, another_owned_stringfica intocado (observe o mutqualificador). Há outra variante que consome o Stringmas não exige que seja mutável. Esta é uma implementação da Addcaracterística que leva a Stringcomo lado esquerdo e a &strcomo lado direito:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    let new_owned_string = owned_string + borrowed_string;
    println!("{}", new_owned_string);
}

Observe que owned_stringnão é mais acessível após a chamada para +.

E se quiséssemos produzir uma nova string, deixando as duas intocadas? A maneira mais simples é usar format!:

fn main() {
    let borrowed_string: &str = "hello ";
    let another_borrowed_string: &str = "world";

    let together = format!("{}{}", borrowed_string, another_borrowed_string);
    println!("{}", together);
}

Observe que as duas variáveis ​​de entrada são imutáveis; portanto, sabemos que elas não são tocadas. Se quisermos fazer o mesmo para qualquer combinação de String, podemos usar o fato de que Stringtambém pode ser formatado:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let another_owned_string: String = "world".to_owned();

    let together = format!("{}{}", owned_string, another_owned_string);
    println!("{}", together);
}

Você não precisa usar isso format!. Você pode clonar uma sequência e anexá-la à nova sequência:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    let together = owned_string.clone() + borrowed_string;
    println!("{}", together);
}

Nota - toda a especificação de tipo que fiz é redundante - o compilador pode inferir todos os tipos em jogo aqui. Eu os adicionei simplesmente para ficar claro para as pessoas novas no Rust, pois espero que essa pergunta seja popular com esse grupo!

Shepmaster
fonte
2
O que você acha Add/ +símbolo? Você pode cobrir se quiser.
bluss
Talvez isso seja simples o suficiente, mas compreendê-lo exige a observação das possíveis assinaturas de tipo para Adicionar com String.
bluss
Obrigado! Você é capaz de se aprofundar um pouco mais em como & String pode ser desreferenciada como & str? Qual parte de sua implementação permite isso e / ou onde diz isso no documento?
jsalter
1
@jsalter, que é um tópico bastante separado, portanto pode ser bom como outra pergunta de nível superior. Eu atualizei a ligação com os documentos apropriados (tão próximo quanto eu posso conseguir, pelo menos ...)
Shepmaster
10
@ ChrisMorgan Note-se que a discrepância .to_owned()e .to_string()foi corrigida desde o comentário acima, graças à especialização impl. Ambos agora têm o mesmo desempenho quando chamados a &str. Confirmação
chad
49

Para concatenar várias cadeias de caracteres em uma única cadeia, separadas por outro caractere, há duas maneiras.

O mais legal que eu já vi é usar o joinmétodo em uma matriz:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = [a, b].join("\n");

    print!("{}", result);
}

Dependendo do seu caso de uso, você também pode preferir mais controle:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = format!("{}\n{}", a, b);

    print!("{}", result);
}

Existem algumas maneiras mais manuais que eu já vi, algumas evitando uma ou duas alocações aqui e ali. Para fins de legibilidade, acho que os dois acima são suficientes.

Simon Whitehead
fonte
Onde está joindocumentado? Parece estar no meio do caminho entre uma matriz e uma string. Eu procurei na documentação da matriz e fiquei rapidamente confuso.
Duane J
3
@DuaneJ joinestá realmente ligado à SliceContactExtcaracterística . A característica é marcada como instável, mas seus métodos são estáveis ​​e estão incluídos no Prelude, para que possam ser usados ​​em qualquer lugar por padrão. A equipe parece estar ciente de que essa característica não precisa existir e eu imagino que as coisas mudarão no futuro com ela.
22618 Simon Simonhead
9

Eu acho que esse concatmétodo e +deve ser mencionado aqui também:

assert_eq!(
  ("My".to_owned() + " " + "string"),
  ["My", " ", "string"].concat()
);

e também há concat!macro, mas apenas para literais:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
suside
fonte
+já foi mencionado em uma resposta existente . ( Esta é uma implementação do Addtraço que leva a Stringque o lado esquerdo e um &strcomo o lado direito: )
Shepmaster
É verdade que a resposta existente é tão ampla que nem percebi.
suside 15/01
6

Maneiras simples de concatenar seqüências de caracteres no RUST

Existem vários métodos disponíveis no RUST para concatenar seqüências de caracteres

Primeiro método (Usando concat!()):

fn main() {
    println!("{}", concat!("a", "b"))
}

A saída do código acima é:

ab


Segundo método (usando push_str()e +operador):

fn main() {
    let mut _a = "a".to_string();
    let _b = "b".to_string();
    let _c = "c".to_string();

    _a.push_str(&_b);
    
    println!("{}", _a);
 
    println!("{}", _a + &_b);
}

A saída do código acima é:

ab

abc


Terceiro método ( Using format!()):

fn main() {
    let mut _a = "a".to_string();
    let _b = "b".to_string();
    let _c = format!("{}{}", _a, _b);
    
    println!("{}", _c);
}

A saída do código acima é:

ab

confira e experimente o Rust play ground

ASHWIN RAJEEV
fonte
Esta resposta não adiciona nada de novo às respostas existentes.
Shepmaster 14/01