Skip to content

Instantly share code, notes, and snippets.

@kellywoo
Last active April 26, 2021 02:20
Show Gist options
  • Save kellywoo/42ce99615d68cb66f7e4bef1d120dadf to your computer and use it in GitHub Desktop.
Save kellywoo/42ce99615d68cb66f7e4bef1d120dadf to your computer and use it in GitHub Desktop.
stringify
function* pipe(arr, operators) {
if (!Array.isArray(arr)) {
throw 'It is not Array.';
}
if (!Array.isArray(operators)) {
throw 'operators should be type of Array<[type: string; fn: (v:any) => any]>';
}
const cpArr = [...arr];
let muatated = [];
let i = 0;
for (const v of cpArr) {
i++;
let value = v;
let shouldShiftOut = false;
for (const op of operators) {
try {
switch (op[0]) {
case 'filter' :
if (!op[1](value)) {
shouldShiftOut = true;
}
break;
case 'map' :
value = op[1](value);
break;
default:
throw 'not supporting method';
}
if (shouldShiftOut) break;
} catch (e) {
throw e;
}
}
if (!shouldShiftOut) {
muatated.push(value);
}
if (i === cpArr.length) {
return muatated;
} else {
yield null;
}
}
}
const m = pipe([1,2,3,4,5,6,7], [['filter', (v)=>v%2 ===0], ['map', (v)=> v*2 ]]);
const {stringify} = (() => {
// simple
const strRegexp = [[/\\/g, '\\\\'], [/\n/g, '\\n'], [/\t/g, '\\t'], [/\v/g, '\\v'], [/[\b]/g, '\\b'], [/[\r]/g, '\\r'], [/"/g, '\\"']]
class ResultRecords {
constructor() {
this.data = [];
}
}
// complex
const complexType = {
array: 'array',
object: 'object',
itemRecord: 'itemRecord',
}
const complexHandlers = {
[complexType.array]: {
createGen: function* (obj) {
for (const v of obj) yield {value: v};
},
createRecords: () => {
return new class extends ResultRecords {
join() {
return `[${this.data.join(',')}]`;
}
push(str) {
this.data.push(str)
}
}
},
},
[complexType.object]: {
createGen: function* (obj) {
for (const k in obj) if (obj.hasOwnProperty(k)) yield {key: k, value: obj[k]};
},
createRecords: () => {
return new class extends ResultRecords {
join() {
return `{${this.data.map((m) => {
return `${typeHandler.string(m[0].toString())}:${m[1]}`;
}).join(',')}}`
}
push(str, key) {
this.data.push([key, str])
}
}
},
}
}
const typeHandler = {
default: () => 'null',
boolean: v => v.toString(),
number: v => {
if (isNaN(v) || !isFinite(v)) {
return typeHandler.default();
}
return v === 0 ? '0' : v.toString();
},
string: (str, i = 0) => {
if (i === strRegexp.length) return `"${str}"`;
return str ? typeHandler.string(str.replace(strRegexp[i][0], strRegexp[i][1]), ++i) : typeHandler.string(str, strRegexp.length);
},
[complexType.itemRecord]: (record) => {
return record.join();
}
}
const processGenerator = (gen, records, stack = null) => {
const {value, done} = gen.next();
if (done) {
return typeRouter(records, stack);
} else {
const target = value.value;
const currentStack = {gen, records, key: value.key, previous: stack};
return typeRouter(target, currentStack);
}
}
const getType = (v) => {
const t = typeof v
if (t === 'object') {
switch (true) {
case !v:
return 'null';
case v instanceof ResultRecords:
return complexType.itemRecord;
case Array.isArray(v):
return complexType.array;
default:
return complexType.object;
}
} else {
return t;
}
}
const typeRouter = (v, stack) => {
const t = getType(v);
if ([complexType.array, complexType.object].includes(t)) {
const gen = complexHandlers[t].createGen(v);
const records = complexHandlers[t].createRecords();
return processGenerator(gen, records, stack);
}
const str = (typeHandler[t] || typeHandler.default)(v);
if (stack) {
const {gen, records, key, previous} = stack;
records.push(str, key);
return processGenerator(gen, records, previous);
} else {
return str
}
}
const stringify = (v) => {
return typeRouter(v);
}
return {stringify};
})();
const {stringify} = (() => {
// simple
const strRegexp = [[/\\/g, '\\\\'], [/\n/g, '\\n'], [/\t/g, '\\t'], [/\v/g, '\\v'], [/[\b]/g, '\\b'], [/[\r]/g, '\\r'], [/"/g, '\\"']]
class ResultRecords {
constructor() {
this.data = [];
}
}
// complex
const complexType = {
array: 'array',
object: 'object',
itemRecord: 'itemRecord',
}
const complexHandlers = {
[complexType.array]: {
createGen: function* (obj) {
for (const v of obj) yield {value: v};
},
createRecords: () => {
return new class extends ResultRecords {
join() {
return `[${this.data.join(',')}]`;
}
push(str) {
this.data.push(str)
}
}
},
},
[complexType.object]: {
createGen: function* (obj) {
for (const k in obj) if (obj.hasOwnProperty(k)) yield {key: k, value: obj[k]};
},
createRecords: () => {
return new class extends ResultRecords {
join() {
return `{${this.data.map((m) => {
return `${typeHandler.string(m[0].toString())}:${m[1]}`;
}).join(',')}}`
}
push(str, key) {
this.data.push([key, str])
}
}
},
}
}
const typeHandler = {
default: () => 'null',
boolean: v => v.toString(),
number: v => {
if (isNaN(v) || !isFinite(v)) {
return typeHandler.default();
}
return v === 0 ? '0' : v.toString();
},
string: (str, i = 0) => {
if (i === strRegexp.length) return `"${str}"`;
return str ? typeHandler.string(str.replace(strRegexp[i][0], strRegexp[i][1]), ++i) : typeHandler.string(str, strRegexp.length);
},
[complexType.itemRecord]: (record) => {
return record.join();
}
}
const processGenerator = (gen, records, stack) => {
const {value, done} = gen.next();
if (done) {
return typeRouter(records, stack);
} else {
const target = value.value;
const currentStack = {gen, records, key: value.key, previous: stack};
return typeRouter(target, currentStack);
}
}
const getType = (v) => {
const t = typeof v
if (t === 'object') {
switch (true) {
case !v:
return 'null';
case v instanceof ResultRecords:
return complexType.itemRecord;
case Array.isArray(v):
return complexType.array;
default:
return complexType.object;
}
} else {
return t;
}
}
const typeRouter = (v, stack) => {
const t = getType(v);
if ([complexType.array, complexType.object].includes(t)) {
const gen = complexHandlers[t].createGen(v);
const records = complexHandlers[t].createRecords();
return processGenerator(gen, records, stack);
}
const str = (typeHandler[t] || typeHandler.default)(v);
if (stack) {
const {gen, records, key, previous} = stack;
records.push(str, key);
return processGenerator(gen, records, previous);
} else {
return str
}
}
const stringify = (v) => {
return typeRouter(v, null);
}
return {stringify};
})();
@kellywoo
Copy link
Author

과제 하나 더 있는거 아시죠?

앗..넵.. 확인했습니다. :)
근데 내주신 의도랑 맞는지는 잘 모르겠습니다.... 혹시 의도가 아니라면 말씀해주세요... :)

@hikaMaeng
Copy link

네. 의도와 달라요 ^^ 개별로 된 두개의 제네레이터를 작성하고 합성해주세요. 특히 yield* 를 사용해주세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment