Query

183 阅读1分钟

function groupBy(array, key) {
  const groups = array.reduce((result, current) => {
    if (Object.prototype.hasOwnProperty.call(current, key)) {
      if (result[current[key]]) {
        result[current[key]] = [...result[current[key]], current];
      } else {
        result[current[key]] = [current];
      }
    }
    return result;
  }, {});
  return Object.values(groups);
}

function Query(data) {
  this.data = data;
  this.queue = [];

  this.compose = function (fn) {
    this.queue.push(fn);
    return this;
  };
}

Query.prototype = {
  where: function (predicate) {
    return this.compose(function () {
      this.data = this.data.filter(predicate);
    });
  },
  orderBy: function (key, desc) {
    return this.compose(function () {
      this.data = this.data.sort((current, next) =>
        desc ? next[key] - current[key] : current[key] - next[key]
      );
    });
  },
  groupBy: function (key) {
    return this.compose(function () {
      this.data = groupBy(this.data, key);
    });
  },
  execute: function () {
    this.queue.forEach((fn) => fn.apply(this));
    return this.data;
  },
};

function query(data) {
  if (!Array.isArray(data)) {
    throw new TypeError(`${data} is not a array`);
  }
  return new Query(data);
}

// test

const testData = [
  { name: "foo", age: 16, city: "shanghai" },
  { name: "bar", age: 24, city: "hangzhou" },
  { name: "fiz", age: 22, city: "shanghai" },
  { name: "baz", age: 19, city: "hangzhou" },
];

console.log(
  query({})
    .where((item) => item.age > 15)
    .orderBy("age", true)
    .groupBy("city")
    .execute()
);