できない.dev

配列を文字列に連結するには

配列(リスト)の要素を区切り文字でつないで 1 本の文字列にする基本形を各言語で示す。
要素が文字列でない場合の扱いが言語ごとに違う点までを扱う。

公開:

各言語見出しの横のバッジは検証状態を表す。実行確認済みはコードを実際に実行して確認したもの、静的確認は構文と公式 API ドキュメントで確認したものである。

Python 実行確認済み

words = ["2026-08-04", "tokyo", "rain"]
print(",".join(words))              # -> 2026-08-04,tokyo,rain
 
nums = [1, 2, 3]
print(",".join(map(str, nums)))     # join は str 以外を受け付けない -> 1,2,3
print(" / ".join(w.upper() for w in words))  # ジェネレータも渡せる

str.join は「区切り文字」側のメソッドで、引数に渡した反復可能オブジェクトの要素を連結する。
要素に数値が混じると TypeError になるため、map(str, ...) で先に文字列化しておく。

うまくいかない時: Python で「TypeError: can only concatenate str (not "int") to str」が直らない

JavaScript 実行確認済み

const words = ["2026-08-04", "tokyo", "rain"];
console.log(words.join(","));      // -> 2026-08-04,tokyo,rain
 
console.log([1, 2, 3].join(","));  // 数値は自動で文字列化される -> 1,2,3
console.log(["a", null, undefined, "b"].join("-")); // -> a---b
console.log(["a", "b"].join());    // 引数を省くと区切りは "," -> a,b

Array.prototype.join は要素を暗黙に文字列化するので、数値の配列でもそのまま渡せる。
ただし null と undefined は空文字に変換されるため、欠損を残したくないときは事前に filter で除く。

TypeScript 実行確認済み

const words: string[] = ["2026-08-04", "tokyo", "rain"];
const line: string = words.join(",");
console.log(line);                 // -> 2026-08-04,tokyo,rain
 
const nums: number[] = [1, 2, 3];
console.log(nums.join(","));       // number[] でも戻り値の型は string

join の戻り値は要素の型にかかわらず string になるため、number[] を連結しても型注釈は string でよい。
区切り文字を変数にする場合は string 型に固定しておくと意図しない undefined 混入を防げる。

Go 静的確認

package main
 
import (
	"fmt"
	"strconv"
	"strings"
)
 
func main() {
	words := []string{"2026-08-04", "tokyo", "rain"}
	fmt.Println(strings.Join(words, ","))
 
	nums := []int{1, 2, 3}
	parts := make([]string, 0, len(nums))
	for _, n := range nums {
		parts = append(parts, strconv.Itoa(n))
	}
	fmt.Println(strings.Join(parts, ","))
}

strings.Join は []string しか受け取らないため、数値のスライスは strconv.Itoa などで先に []string へ変換する必要がある。
容量を len で確保しておくと連結時の再確保を避けられる。

Rust 静的確認

fn main() {
    let words = vec!["2026-08-04", "tokyo", "rain"];
    println!("{}", words.join(","));
 
    let nums = vec![1, 2, 3];
    let joined: String = nums
        .iter()
        .map(|n| n.to_string())
        .collect::<Vec<_>>()
        .join(",");
    println!("{}", joined);
}

&str や String のスライスには join が生えており、戻り値は String になる。
数値のベクタには直接使えないので、to_string でいったん文字列へ写してから連結する。

Java 実行確認済み

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class Join {
    public static void main(String[] args) {
        List<String> words = List.of("2026-08-04", "tokyo", "rain");
        System.out.println(String.join(",", words));
 
        List<Integer> nums = List.of(1, 2, 3);
        System.out.println(nums.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(",")));
        System.out.println(Stream.of("a", "b")
                .collect(Collectors.joining(", ", "[", "]")));
    }
}

String.join は CharSequence の並びだけを受け取るため、数値のリストは String::valueOf で写してから Collectors.joining に渡す。
joining は前後の飾り文字も同時に指定できるので、括弧付きの出力もひと息で作れる。

C# 静的確認

using System;
using System.Linq;
 
class Program
{
    static void Main()
    {
        string[] words = { "2026-08-04", "tokyo", "rain" };
        Console.WriteLine(string.Join(",", words));
 
        int[] nums = { 1, 2, 3 };
        Console.WriteLine(string.Join(",", nums));  // 数値でもそのまま渡せる
        Console.WriteLine(string.Join(", ", words.Select(w => w.ToUpper())));
    }
}

string.Join にはジェネリックな IEnumerable<T> を取るオーバーロードがあり、各要素の ToString が呼ばれるため数値配列も変換なしで連結できる。
LINQ の Select を挟めば加工と連結を 1 行で書ける。

つまずき

最も多い失敗は、文字列以外の要素をそのまま連結しようとすることである。
Python の str.join と Go の strings.Join、Java の String.join は文字列だけを受け取るため、数値のコレクションは先に文字列へ写す必要がある。
一方 JavaScript / TypeScript と C# は暗黙に ToString 相当を呼ぶので変換が要らない。
この差を知らずに移植すると、実行時例外やコンパイルエラーの形で表面化する。

空要素と区切り文字の扱い

JavaScript の join は null と undefined を空文字として扱うため、要素が欠けていても区切り文字だけが残る。
欠損を落としたいなら filter で除いてから連結する。
区切り文字を省略したときの既定値も言語ごとに違い、JavaScript はカンマになるが Python や Go では引数の省略自体ができない。
意図した区切りを常に明示しておくと移植時に事故が起きにくい。