02020 / vite-kit

0 stars 0 forks source link

Chainer #11

Open 02020 opened 1 year ago

02020 commented 1 year ago
type Obj<T> = { [key: string]: T };
type PredicateFn<T> = (item: T) => boolean;
type MapFn<T, U> = (item: T) => U;
type JoinFn<T, U> = (item: T, otherItem: U) => boolean;
type CombineFn<T, U, V> = (item: T, otherItem: U) => V;
type ReduceFn<T, U> = (acc: U, item: T) => U;

function chain<T>(data: T[]): Chainer<T>;
function filter<T>(pred: PredicateFn<T>): (data: T[]) => T[];
function map<T, U>(fn: MapFn<T, U>): (data: T[]) => U[];
function join<T, U, V>(
  otherData: U[],
  joinFn: JoinFn<T, U>,
  combineFn?: CombineFn<T, U, V>
): (data: T[]) => V[];
function reduce<T, U>(fn: ReduceFn<T, U>, acc: U): (data: T[]) => U;
function merge<T>(...objs: Obj<T>[]): Obj<T>;

class Chainer<T> {
  constructor(private data: T[]) {}

  static from<T>(data: T[]): Chainer<T> {
    return new Chainer(data);
  }

  filter(pred: PredicateFn<T>): Chainer<T> {
    this.data = this.data.filter(pred);
    return this;
  }

  map<U>(fn: MapFn<T, U>): Chainer<U> {
    const newData = this.data.map(fn);
    return new Chainer(newData);
  }

  join<U, V>(
    otherData: U[],
    joinFn: JoinFn<T, U>,
    combineFn?: CombineFn<T, U, V>
  ): Chainer<V> {
    const newData: V[] = [];
    for (const item of this.data) {
      for (const otherItem of otherData) {
        if (joinFn(item, otherItem)) {
          newData.push(
            combineFn ? combineFn(item, otherItem) : { ...item, ...otherItem }
          );
        }
      }
    }
    return new Chainer(newData);
  }

  reduce<U>(fn: ReduceFn<T, U>, acc: U): U {
    return this.data.reduce<U>(fn, acc);
  }

  mergeWith<U>(otherData: Obj<U>[]): Chainer<T & U> {
    const newData = Object.assign({}, this.data, ...otherData);
    return new Chainer(newData);
  }

  private groupByInternal<K>(keyFn: (item: T) => K): Map<K, T[]> {
    const groups = new Map<K, T[]>();
    for (const item of this.data) {
      const key = keyFn(item);
      if (groups.has(key)) {
        groups.get(key)!.push(item);
      } else {
        groups.set(key, [item]);
      }
    }
    return groups;
  }

  group<K>(groupFn: (item: T) => K): Chainer<Obj<T>[]> {
    const groups = this.groupByInternal(groupFn);
    return new Chainer(Array.from(groups.values()));
  }

  groupBy<K extends keyof T>(key: K): Chainer<Obj<T>[]> {
    const keyFn = (item: T) => item[key];
    const groups = this.groupByInternal(keyFn);
    return new Chainer(Array.from(groups.values()));
  }

  value(): T[] {
    return this.data;
  }
}
02020 commented 1 year ago
type Predicate<T> = (item: T) => boolean;
type Selector<T, U> = (item: T) => U;
type GroupKeySelector<T, K> = (item: T) => K;

type Collection<T> = {
  filter(predicate: Predicate<T>): Collection<T>;
  map<U>(selector: Selector<T, U>): Collection<U>;
  groupBy<K>(keySelector: GroupKeySelector<T, K>): Map<K, T[]>;
  toArray(): T[];
};

function from<T>(items: T[]): Collection<T> {
  return {
    filter(predicate: Predicate<T>): Collection<T> {
      return from(items.filter(predicate));
    },
    map<U>(selector: Selector<T, U>): Collection<U> {
      return from(items.map(selector));
    },
    groupBy<K>(keySelector: GroupKeySelector<T, K>): Map<K, T[]> {
      const map = new Map<K, T[]>();
      for (const item of items) {
        const key = keySelector(item);
        const group = map.get(key) ?? [];
        group.push(item);
        map.set(key, group);
      }
      return map;
    },
    toArray(): T[] {
      return [...items];
    },
  };
}

interface Person {
  name: string;
  age: number;
}

const people: Person[] = [
  { name: "Alice", age: 25 },
  { name: "Bob", age: 30 },
  { name: "Charlie", age: 35 },
];

const result = from(people)
  .filter((person) => person.age > 25)
  .groupBy((person) => Math.floor(person.age / 10) * 10)
  .map(([ageGroup, people]) => ({
    ageGroup,
    totalAge: people.reduce((sum, person) => sum + person.age, 0),
    count: people.length,
  }))
  .toArray();

console.log(result);
02020 commented 1 year ago
type Predicate<T> = (item: T) => boolean;
type Selector<T, U> = (item: T) => U;
type GroupKeySelector<T, K> = (item: T) => K;

interface Collection<T> {
  filter(predicate: Predicate<T>): Collection<T>;
  map<U>(selector: Selector<T, U>): Collection<U>;
  toArray(): T[];
  pluck<K extends keyof T>(keys: K[]): Collection<Pick<T, K>>;
}

function from<T>(items: T[]): Collection<T> {
  return {
    filter(predicate: Predicate<T>): Collection<T> {
      return from(items.filter(predicate));
    },
    map<U>(selector: Selector<T, U>): Collection<U> {
      return from(items.map((item) => selector(item)));
    },
    toArray(): T[] {
      return items;
    },
    pluck<K extends keyof T>(keys: K[]): Collection<Pick<T, K>> {
      return from(
        items.map((item) =>
          keys.reduce((obj, key) => {
            obj[key] = item[key];
            return obj;
          }, {} as Pick<T, K>)
        )
      );
    },
  };
}
02020 commented 1 year ago
type Predicate<T> = (item: T) => boolean;
type Selector<T, U> = (item: T) => U;
type GroupKeySelector<T, K> = (item: T) => K;

type Collection<T> = {
  filter(predicateFn: Predicate<T>): Collection<T>;
  map<U>(selectorFn: Selector<T, U>): Collection<U>;
  groupBy<K>(keySelectorFn: GroupKeySelector<T, K>): Map<K, T[]>;
  toArray(): T[];
};

function createCollection<T>(itemsArray: T[]): Collection<T> {
  return {
    filter(predicateFn: Predicate<T>): Collection<T> {
      return createCollection(itemsArray.filter(predicateFn));
    },
    map<U>(selectorFn: Selector<T, U>): Collection<U> {
      return createCollection(itemsArray.map(selectorFn));
    },
    groupBy<K>(keySelectorFn: GroupKeySelector<T, K>): Map<K, T[]> {
      const map = new Map<K, T[]>();
      for (const item of itemsArray) {
        const key = keySelectorFn(item);
        const group = map.get(key) ?? [];
        group.push(item);
        map.set(key, group);
      }
      return map;
    },
    toArray(): T[] {
      return [...itemsArray];
    },
  };
}
type Predicate<T> = (item: T) => boolean;
type Selector<T, U> = (item: T) => U;
type GroupKeySelector<T, K> = (item: T) => K;

type Collection<T> = {
  filter: (predicateFn: Predicate<T>) => Collection<T>;
  map: <U>(selectorFn: Selector<T, U>) => Collection<U>;
  groupBy: <K>(keySelectorFn: GroupKeySelector<T, K>) => Map<K, T[]>;
  toArray: () => T[];
};

const createCollection = <T>(itemsArray: T[]): Collection<T> => ({
  filter: (predicateFn) =>
    createCollection(itemsArray.filter(predicateFn)),
  map: (selectorFn) => createCollection(itemsArray.map(selectorFn)),
  groupBy: (keySelectorFn) => {
    const map = new Map();
    for (const item of itemsArray) {
      const key = keySelectorFn(item);
      const group = map.get(key) || [];
      group.push(item);
      map.set(key, group);
    }
    return map;
  },
  toArray: () => [...itemsArray],
});
02020 commented 1 year ago
type UnaryFn<T, R> = (x: T) => R;

function compose<T, R, U>(
  f: UnaryFn<T, R>,
  g: UnaryFn<R, U>
): UnaryFn<T, U> {
  return (x: T) => g(f(x));
}

function pipe<T, R, U>(
  f: UnaryFn<T, R>,
  g: UnaryFn<R, U>
): UnaryFn<T, U> {
  return (x: T) => f(g(x));
}

function add(x: number): UnaryFn<number, number> {
  return (y: number) => x + y;
}

function subtract(x: number): UnaryFn<number, number> {
  return (y: number) => x - y;
}

function multiply(x: number): UnaryFn<number, number> {
  return (y: number) => x * y;
}

function divide(x: number): UnaryFn<number, number> {
  return (y: number) => x / y;
}

const result = compose(
  add(10),
  divide(2),
  subtract(3),
  multiply(2)
)(5);

console.log(result); // Output: 9
class Calculator {
  private readonly initial: number;

  constructor(initial: number) {
    this.initial = initial;
  }

  add(value: number): Calculator {
    return new Calculator(this.initial + value);
  }

  subtract(value: number): Calculator {
    return new Calculator(this.initial - value);
  }

  multiply(value: number): Calculator {
    return new Calculator(this.initial * value);
  }

  divide(value: number): Calculator {
    return new Calculator(this.initial / value);
  }

  getResult(): number {
    return this.initial;
  }
}

const result = new Calculator(10)
  .add(5)
  .multiply(2)
  .subtract(3)
  .divide(4)
  .getResult();

console.log(result); // Output: 3.25
02020 commented 1 year ago
type PipeFunction<T, U> = (data: T[]) => U[];

function filter<T>(predicate: (item: T) => boolean): PipeFunction<T, T> {
  return (data) => data.filter(predicate);
}

function map<T, U>(mapper: (item: T) => U): PipeFunction<T, U> {
  return (data) => data.map(mapper);
}

function flatMap<T, U>(mapper: (item: T) => U[]): PipeFunction<T, U> {
  return (data) => data.flatMap(mapper);
}

function pipe<T, U>(data: T[], ...fns: PipeFunction<any, any>[]): U[] {
  return fns.reduce((result, fn) => fn(result), data);
}

// 使用示例
const data = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 40 },
];

const result = pipe(
  data,
  filter((item) => item.age >= 30),
  map((item) => item.name)
);

console.log(result); // ['Bob', 'Charlie']
class Pipeline<T> {
  private readonly data: T[];

  constructor(data: T[]) {
    this.data = data;
  }

  filter(predicate: (item: T) => boolean): Pipeline<T> {
    const filteredData = this.data.filter(predicate);
    return new Pipeline(filteredData);
  }

  map<U>(mapper: (item: T) => U): Pipeline<U> {
    const mappedData = this.data.map(mapper);
    return new Pipeline(mappedData);
  }

  flatMap<U>(mapper: (item: T) => U[]): Pipeline<U> {
    const flatMappedData = this.data.flatMap(mapper);
    return new Pipeline(flatMappedData);
  }

  toArray(): T[] {
    return this.data;
  }
}

// 使用示例
const data = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 40 },
];

const result = new Pipeline(data)
  .filter((item) => item.age >= 30)
  .map((item) => item.name)
  .toArray();

console.log(result); // ['Bob', 'Charlie']