Event Emitter
Implement a pub/sub event emitter with on / off / emit — the pattern behind app-wide events and notifications. Subscriptions return an id so a single listener can be removed.
Sample input
on("greet", hello); on("greet", hi); emit("greet","Alice"); off greet1; emit("greet","Bob")
Sample output
Hello Alice
Hi Alice
Hi Bob
Solution
class EventEmitter:
def __init__(self):
self.listeners = {}
self.next_id = 0
def on(self, event, callback):
self.next_id += 1
self.listeners.setdefault(event, []).append((self.next_id, callback))
return self.next_id
def off(self, event, sub_id):
if event in self.listeners:
self.listeners[event] = [(i, cb) for (i, cb) in self.listeners[event] if i != sub_id]
def emit(self, event, arg):
for (_, cb) in self.listeners.get(event, []):
cb(arg)
emitter = EventEmitter()
id1 = emitter.on("greet", lambda name: print("Hello " + name))
emitter.on("greet", lambda name: print("Hi " + name))
emitter.emit("greet", "Alice")
emitter.off("greet", id1)
emitter.emit("greet", "Bob")
class EventEmitter {
constructor() {
this.listeners = {};
this.nextId = 0;
}
on(event, callback) {
const id = ++this.nextId;
(this.listeners[event] = this.listeners[event] || []).push({ id, callback });
return id;
}
off(event, id) {
if (this.listeners[event]) {
this.listeners[event] = this.listeners[event].filter(l => l.id !== id);
}
}
emit(event, arg) {
(this.listeners[event] || []).forEach(l => l.callback(arg));
}
}
const emitter = new EventEmitter();
const id1 = emitter.on("greet", name => console.log("Hello " + name));
emitter.on("greet", name => console.log("Hi " + name));
emitter.emit("greet", "Alice");
emitter.off("greet", id1);
emitter.emit("greet", "Bob");
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class Main {
static class EventEmitter {
static class Listener {
int id;
Consumer<String> cb;
Listener(int id, Consumer<String> cb) { this.id = id; this.cb = cb; }
}
Map<String, List<Listener>> listeners = new HashMap<>();
int nextId = 0;
int on(String event, Consumer<String> cb) {
int id = ++nextId;
listeners.computeIfAbsent(event, k -> new ArrayList<>()).add(new Listener(id, cb));
return id;
}
void off(String event, int id) {
if (listeners.containsKey(event)) {
listeners.get(event).removeIf(l -> l.id == id);
}
}
void emit(String event, String arg) {
for (Listener l : listeners.getOrDefault(event, new ArrayList<>())) {
l.cb.accept(arg);
}
}
}
public static void main(String[] args) {
EventEmitter emitter = new EventEmitter();
int id1 = emitter.on("greet", name -> System.out.println("Hello " + name));
emitter.on("greet", name -> System.out.println("Hi " + name));
emitter.emit("greet", "Alice");
emitter.off("greet", id1);
emitter.emit("greet", "Bob");
}
}
class EventEmitter {
private val listeners = HashMap<String, MutableList<Pair<Int, (String) -> Unit>>>()
private var nextId = 0
fun on(event: String, cb: (String) -> Unit): Int {
nextId++
listeners.getOrPut(event) { mutableListOf() }.add(Pair(nextId, cb))
return nextId
}
fun off(event: String, id: Int) {
listeners[event]?.removeAll { it.first == id }
}
fun emit(event: String, arg: String) {
listeners[event]?.forEach { it.second(arg) }
}
}
fun main() {
val emitter = EventEmitter()
val id1 = emitter.on("greet") { name -> println("Hello $name") }
emitter.on("greet") { name -> println("Hi $name") }
emitter.emit("greet", "Alice")
emitter.off("greet", id1)
emitter.emit("greet", "Bob")
}
class EventEmitter {
var listeners: [String: [(id: Int, cb: (String) -> Void)]] = [:]
var nextId = 0
func on(_ event: String, _ cb: @escaping (String) -> Void) -> Int {
nextId += 1
listeners[event, default: []].append((id: nextId, cb: cb))
return nextId
}
func off(_ event: String, _ id: Int) {
listeners[event]?.removeAll { $0.id == id }
}
func emit(_ event: String, _ arg: String) {
for listener in listeners[event] ?? [] {
listener.cb(arg)
}
}
}
let emitter = EventEmitter()
let id1 = emitter.on("greet") { name in print("Hello " + name) }
_ = emitter.on("greet") { name in print("Hi " + name) }
emitter.emit("greet", "Alice")
emitter.off("greet", id1)
emitter.emit("greet", "Bob")
class EventEmitter {
final Map<String, List<MapEntry<int, void Function(String)>>> listeners = {};
int nextId = 0;
int on(String event, void Function(String) cb) {
nextId++;
listeners.putIfAbsent(event, () => []).add(MapEntry(nextId, cb));
return nextId;
}
void off(String event, int id) {
listeners[event]?.removeWhere((l) => l.key == id);
}
void emit(String event, String arg) {
for (final l in listeners[event] ?? []) {
l.value(arg);
}
}
}
void main() {
final emitter = EventEmitter();
final id1 = emitter.on('greet', (name) => print('Hello $name'));
emitter.on('greet', (name) => print('Hi $name'));
emitter.emit('greet', 'Alice');
emitter.off('greet', id1);
emitter.emit('greet', 'Bob');
}
#include <iostream>
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;
class EventEmitter {
struct Listener {
int id;
function<void(const string&)> cb;
};
unordered_map<string, vector<Listener>> listeners;
int nextId = 0;
public:
int on(const string& event, function<void(const string&)> cb) {
int id = ++nextId;
listeners[event].push_back({id, cb});
return id;
}
void off(const string& event, int id) {
auto& vec = listeners[event];
for (size_t i = 0; i < vec.size(); i++) {
if (vec[i].id == id) {
vec.erase(vec.begin() + i);
break;
}
}
}
void emit(const string& event, const string& arg) {
for (auto& l : listeners[event]) {
l.cb(arg);
}
}
};
int main() {
EventEmitter emitter;
int id1 = emitter.on("greet", [](const string& name) { cout << "Hello " << name << endl; });
emitter.on("greet", [](const string& name) { cout << "Hi " << name << endl; });
emitter.emit("greet", "Alice");
emitter.off("greet", id1);
emitter.emit("greet", "Bob");
return 0;
}
#include <stdio.h>
typedef void (*Callback)(const char *);
#define MAX 10
int ids[MAX];
Callback callbacks[MAX];
int count = 0;
int nextId = 0;
void hello(const char *name) { printf("Hello %s\n", name); }
void hi(const char *name) { printf("Hi %s\n", name); }
int on(Callback cb) {
nextId++;
ids[count] = nextId;
callbacks[count] = cb;
count++;
return nextId;
}
void off(int id) {
for (int i = 0; i < count; i++) {
if (ids[i] == id) {
for (int j = i; j < count - 1; j++) {
ids[j] = ids[j + 1];
callbacks[j] = callbacks[j + 1];
}
count--;
break;
}
}
}
void emit(const char *arg) {
for (int i = 0; i < count; i++) {
callbacks[i](arg);
}
}
int main() {
int id1 = on(hello);
on(hi);
emit("Alice");
off(id1);
emit("Bob");
return 0;
}