{ }codelper
splitting stringsmap lookupP0236

Read the settings after the address

You are given one line: the settings string that follows the question mark in a web address. The settings string consists only of lowercase English letters, digits, '=' and '&'. First split the settings string on '&'. Drop every empty piece.
An empty piece appears when two & are next to each other, or when & is at the very start or the very end. For each remaining piece, the part before the first '=' is the name and the part after it is the value. A value may contain more '=' characters, and a value may be the empty string. A piece with no '=' is entirely a name, and its value is the empty string. No piece starts with '='. The second line gives the number of questions q, and each of the next q lines gives one name. On the first line, print the number of remaining pieces. Then, for each question, print on one line the values of the pieces with that name, in the order they appear, each wrapped in square brackets and joined with no spaces. An empty value is printed as []. If no piece has that name, print -.

Input
The settings string has 1 to 10,000 characters, 1 ≤ q ≤ 100, each asked name has 1 to 10 lowercase letters and digits
Output
The number of pieces on the first line, then for each of the q questions its values or -
Example 1 · stdin
page=2&sort=new&&tag=a&tag=b=c&debug&
4
tag
debug
page
size
stdout
5
[a][b=c]
[]
[2]
-
Example 2 · stdin
&&&
1
a
stdout
0
-
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

All 8 languages have a split function, but each treats empty pieces and the number of splits differently.
Python split("&"), JS/TS split("&") and Craykon Split("&") keep empty pieces, so "&&&" becomes 4 empty strings and you must filter them yourself.
Java split("&") splits on a regex and drops only the trailing empty pieces, keeping the leading and middle ones.
C# Split('&', StringSplitOptions.RemoveEmptyEntries) drops them all.
C strtok treats consecutive & as one and skips empty pieces, which is exactly right for '&'.
But if you also cut '=' with strtok, the value "=" of "k==" disappears, so find only the first '=' with strchr.
C++'s std::string has no split function; the usual way is to take pieces one by one with getline(stream, piece, '&') and cut with find('=').
The trap in this problem is splitting on '=' only once.
Python partition("=") or split("=", 1), Java split("=", 2) and C# Split('=', 2) cut only at the first '=' and leave the rest in the value.
JS/TS split("=", 2) has the same name but a different meaning.
It keeps only the first two pieces and throws the rest away, so "b=c=d" becomes ["b", "c"]; cut with indexOf("=") and slice instead.
Craykon also cuts with IndexOf("=") and Substring.
Splitting with no limit, as in Java split("="), turns "k==" into ["k"] and the whole value is lost.
When a name appears twice every value must be shown, so the dictionary holds a list of values, not a single value.

Pythonmain.py · 18 lines
line = input()q = int(input())values = {}  # 이름 → 값 목록(나온 차례대로)count = 0for piece in line.split("&"):    if piece == "":        continue  # &&·맨 앞·맨 뒤의 &가 만든 빈 조각은 버린다    count += 1    # 처음 나오는 '='에서만 한 번 나눈다(값 안의 '='는 그대로)    name, _, value = piece.partition("=")    values.setdefault(name, []).append(value)print(count)for _ in range(q):    name = input().strip()    if name in values:        print("".join(f"[{v}]" for v in values[name]))    else:        print("-")
JavaScriptmain.js · 20 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[1]);const values = new Map(); // 이름 → 값 배열(나온 차례대로)let count = 0;for (const piece of lines[0].trim().split("&")) {  if (piece === "") continue; // 빈 조각은 버린다  count++;  // 처음 나오는 '='에서만 자른다. split("=")은 값 안의 '='까지 자른다  const at = piece.indexOf("=");  const name = at < 0 ? piece : piece.slice(0, at);  const value = at < 0 ? "" : piece.slice(at + 1);  if (!values.has(name)) values.set(name, []);  values.get(name).push(value);}const out = [String(count)];for (let i = 0; i < q; i++) {  const vs = values.get(lines[2 + i].trim());  out.push(vs ? vs.map((v) => `[${v}]`).join("") : "-");}console.log(out.join("\n"));
TypeScriptmain.ts · 22 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[1]);const values = new Map<string, string[]>(); // 이름 → 값 배열(나온 차례대로)let count = 0;for (const piece of lines[0].trim().split("&")) {  if (piece === "") continue; // 빈 조각은 버린다  count++;  // 처음 나오는 '='에서만 자른다. split("=")은 값 안의 '='까지 자른다  const at: number = piece.indexOf("=");  const name: string = at < 0 ? piece : piece.slice(0, at);  const value: string = at < 0 ? "" : piece.slice(at + 1);  const list: string[] = values.get(name) ?? [];  list.push(value);  values.set(name, list);}const out: string[] = [String(count)];for (let i = 0; i < q; i++) {  const vs: string[] | undefined = values.get(lines[2 + i].trim());  out.push(vs ? vs.map((v) => `[${v}]`).join("") : "-");}console.log(out.join("\n"));
JavaMain.java · 37 lines
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        String line = in.readLine().trim();        int q = Integer.parseInt(in.readLine().trim());        Map<String, List<String>> values = new HashMap<>(); // 이름 → 값 목록(나온 차례대로)        int count = 0;        // Java의 split은 맨 뒤의 빈 조각을 버리지만 맨 앞·가운데의 빈 조각은 남긴다        for (String piece : line.split("&")) {            if (piece.isEmpty()) continue;            count++;            // 한도 2: 처음 '='에서 한 번만 자르고, 뒤의 빈 문자열도 남긴다            String[] kv = piece.split("=", 2);            String value = kv.length > 1 ? kv[1] : "";            values.computeIfAbsent(kv[0], k -> new ArrayList<>()).add(value);        }        StringBuilder out = new StringBuilder();        out.append(count).append('\n');        for (int i = 0; i < q; i++) {            List<String> vs = values.get(in.readLine().trim());            if (vs == null) {                out.append("-\n");                continue;            }            for (String v : vs) out.append('[').append(v).append(']');            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 43 lines
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        string line = Console.ReadLine().Trim();        int q = int.Parse(Console.ReadLine());        var values = new Dictionary<string, List<string>>(); // 이름 → 값 목록(나온 차례대로)        int count = 0;        // RemoveEmptyEntries가 빈 조각을 버린다        foreach (string piece in line.Split('&', StringSplitOptions.RemoveEmptyEntries))        {            count++;            // 한도 2: 처음 '='에서 한 번만 자른다            string[] kv = piece.Split('=', 2);            string value = kv.Length > 1 ? kv[1] : "";            if (!values.TryGetValue(kv[0], out var list))            {                list = new List<string>();                values[kv[0]] = list;            }            list.Add(value);        }        var sb = new StringBuilder();        sb.Append(count).Append('\n');        for (int i = 0; i < q; i++)        {            if (values.TryGetValue(Console.ReadLine().Trim(), out var vs))            {                foreach (string v in vs) sb.Append('[').Append(v).Append(']');                sb.Append('\n');            }            else            {                sb.Append("-\n");            }        }        Console.Write(sb);    }}
C++main.cpp · 36 lines
#include <iostream>#include <map>#include <sstream>#include <string>#include <vector> int main() {    std::string line, piece;    std::getline(std::cin, line);    if (!line.empty() && line.back() == '\r') line.pop_back();    std::map<std::string, std::vector<std::string>> values; // 이름 → 값 목록(나온 차례대로)    int count = 0;    std::stringstream ss(line);    // getline에 구분 글자를 주면 빈 조각도 하나씩 돌려준다    while (std::getline(ss, piece, '&')) {        if (piece.empty()) continue;        count++;        std::size_t at = piece.find('='); // 처음 '='만        if (at == std::string::npos) values[piece].push_back("");        else values[piece.substr(0, at)].push_back(piece.substr(at + 1));    }    std::cout << count << '\n';    int q;    std::cin >> q;    std::string key;    for (int i = 0; i < q; i++) {        std::cin >> key;        auto it = values.find(key);        if (it == values.end()) {            std::cout << "-\n";            continue;        }        for (const auto &v : it->second) std::cout << '[' << v << ']';        std::cout << '\n';    }}
Cmain.c · 39 lines
#include <stdio.h>#include <string.h> static char line[10005];static char *names[5001], *vals[5001]; int main(void) {    int q, count = 0;    if (!fgets(line, sizeof line, stdin)) return 0;    line[strcspn(line, "\r\n")] = '\0';    /* strtok은 이어진 &를 하나로 보고 빈 조각을 건너뛴다 — 이 문제에는 딱 맞다 */    for (char *piece = strtok(line, "&"); piece; piece = strtok(NULL, "&")) {        /* '='는 strtok으로 자르면 "a==b"의 '='가 사라진다. 처음 '='만 strchr로 찾는다 */        char *eq = strchr(piece, '=');        if (eq) {            *eq = '\0';            vals[count] = eq + 1;        } else {            vals[count] = "";        }        names[count] = piece;        count++;    }    printf("%d\n", count);    scanf("%d", &q);    char key[16];    for (int i = 0; i < q; i++) {        scanf("%15s", key);        int found = 0;        for (int j = 0; j < count; j++) {            if (strcmp(names[j], key) == 0) {                printf("[%s]", vals[j]);                found = 1;            }        }        puts(found ? "" : "-");    }    return 0;}
Craykonmain.cray · 44 lines
line = Console.ReadLine().Trim();q = Console.ReadLine().ToNumber();values = Dict(); // 이름 → 값 목록(나온 차례대로)count = 0;foreach (piece in line.Split("&")){    if (piece == "")    {        continue; // 빈 조각은 버린다    }    count += 1;    // 처음 나오는 '='에서만 자른다    at = piece.IndexOf("=");    name = piece;    value = "";    if (at >= 0)    {        name = piece.Substring(0, at);        value = piece.Substring(at + 1);    }    if (!values.Contains(name))    {        values[name] = [];    }    values[name].Add(value);}Console.WriteLine(count);for (i = 0; i < q; i++){    key = Console.ReadLine().Trim();    if (values.Contains(key))    {        out = "";        foreach (v in values[key])        {            out += "[" + v + "]";        }        Console.WriteLine(out);    }    else    {        Console.WriteLine("-");    }}