Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Trừ hai Set trong JavaScript (Set Difference)

Phép hiệu của hai tập hợp (set difference) trả về một tập mới chỉ chứa các phần tử thuộc tập đầu tiên mà không có trong tập thứ hai. JavaScript không cung cấp sẵn phương thức này cho Set (tính đến ES2024), nhưng bạn có thể triển khai dễ dàng.

Triển khai với class Set tùy chỉnh (MySet)

class MySet {
  constructor() {
    this.items = {};
  }

  add(value) {
    if (!this.has(value)) {
      this.items[value] = value;
      return true;
    }
    return false;
  }

  delete(value) {
    if (this.has(value)) {
      delete this.items[value];
      return true;
    }
    return false;
  }

  has(value) {
    return Object.prototype.hasOwnProperty.call(this.items, value);
  }

  forEach(callback) {
    for (const key in this.items) {
      if (this.has(key)) callback(key);
    }
  }

  // Phương thức tĩnh difference
  static difference(s1, s2) {
    if (!(s1 instanceof MySet) || !(s2 instanceof MySet)) {
      console.log("Đối tượng không phải kiểu MySet");
      return null;
    }
    const newSet = new MySet();
    s1.forEach(elem => newSet.add(elem));
    s2.forEach(elem => newSet.delete(elem));
    return newSet;
  }

  display() {
    console.log(this.items);
  }
}

// Test
const testSet1 = new MySet();
testSet1.add(1);
testSet1.add(2);

const testSet2 = new MySet();
testSet2.add(2);
testSet2.add(5);

const testSet3 = MySet.difference(testSet1, testSet2);
testSet3.display(); // { '1': 1 }

Mở rộng cho Set chuẩn ES6

Bạn có thể thêm phương thức tĩnh trực tiếp vào Set để dùng lại:

Set.difference = function(s1, s2) {
  if (!(s1 instanceof Set) || !(s2 instanceof Set)) {
    console.log("Đối tượng không phải kiểu Set");
    return null;
  }
  const newSet = new Set();
  s1.forEach(elem => newSet.add(elem));
  s2.forEach(elem => newSet.delete(elem));
  return newSet;
};

// Test với Set chuẩn
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 3]);
console.log(Set.difference(setA, setB)); // Set { 1, 4 }

Cách viết hiện đại hơn (ES2015+)

Sử dụng filter và constructor Set cho code ngắn gọn, hàm thuần túy:

const difference = (setA, setB) => 
  new Set([...setA].filter(x => !setB.has(x)));

// Hoặc dùng prototype nếu muốn gọi như method
Set.prototype.difference = function(otherSet) {
  return new Set([...this].filter(x => !otherSet.has(x)));
};

// Usage
const a = new Set([1, 2, 3, 4]);
const b = new Set([2, 3]);
console.log(a.difference(b)); // Set { 1, 4 }

Lưu ý hiệu năng

  • Độ phức tạp thời gian: O(n + m) với n, m là kích thước 2 tập.
  • Set.prototype.has là O(1) trung bình, nên cách dùng filter + has rất hiệu quả.
  • Tránh lặp lồng nhau (O(n×m)) khi xử lý tập lớn.