使用 Ramda 进行逻辑优化
logical optimisation using Ramda
我使用 Ramda 做了一个解析函数,它像一个 charms 一样工作,但我很确定它可以被简化,不幸的是我正在努力克服这个优化
我想将值分组到一个结构中,该结构具有 'name','y' 是计数。例如,如果 'pending' 出现两次, 'hired' 在我的输入中出现一次,那么我想得到你在输出中看到的内容
我写的函数
const aggResumeStatusTest = data =>
reduce(
(acc, elem) => {
if (!isEmpty(acc)) {
const indexInArray = findIndex(propEq('name', elem))(acc);
if (indexInArray !== -1) {
acc[indexInArray].y++;
} else {
acc.push({
name: elem,
y: 1,
});
}
return acc;
}
acc.push({
name: elem,
y: 1,
});
return acc;
},
[],
data,
);
aggResumeStatusTest(['pending', 'pending', 'hired'])
输入
['pending', 'pending', 'hired']
输出
[ { name: 'pending', y: 2 }, { name: 'hired', y: 1 } ]
在此先感谢您的帮助
我不知道这是否算作优化,但您的代码可以简化。
首先,R.groupBy
将所有这些字符串分组。所以你可以从:
['pending', 'pending', 'hired']
收件人:
[['pending', 'pending'], 'hired']
不同之处在于,它 returns 是一个对象,我们只对它的值感兴趣,所以我们使用 R.values
。
然后你所要做的就是映射它并获取它的长度。
所以最后你有:
let countToObj = arr => ({name : R.head(arr), y: arr.length })
R.map(countToObj, R.values(R.groupBy(R.identity, data)));
let countToObj = arr => ({name : R.head(arr), y: arr.length })
let aggResumeStatusTest = data => R.map(countToObj, R.values(R.groupBy(R.identity, data)));
console.log(aggResumeStatusTest(['pending', 'pending', 'hired']));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>
使用 ramda 可以轻松完成此任务,
请看一看 R.countBy
;
const count = R.pipe(
R.countBy(R.identity),
R.toPairs,
R.map(([name, y]) => ({ name, y })),
)
// ====
const data = ['pending', 'pending', 'hired'];
console.log(
count(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
我喜欢将这些问题视为一系列转换,并加入 pipe
或 compose
。
const count = pipe (
countBy (identity),
toPairs,
map (zipObj (['name', 'y']))
)
console .log (count (['pending', 'pending', 'hired']))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj} = R </script>
这里我们先用countBy
转换为{pending: 2, hired: 1}
。然后用 toPairs
,我们得到 [['pending', 2], ['hired', 1]]
。最后,我们map
zipObj
将那些数组转换成合适的对象,[{"name": "pending", "y": 2}, {"name": "hired", "y": 1}]
and 的回答非常好,我完全赞同。
我想展示另一种实现方法。首先使用普通 JavaScript,我们可以对 Map 进行计数,然后将该 map 作为可迭代对象 Array.from
转换为对象:
const countBy = (mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
};
const identity = x => x;
const count = input =>
Array.from(
countBy(identity, input),
([name, y]) => ({name, y})
);
console.log(count(['pending', 'pending', 'hired']));
.as-console-wrapper {
max-height: 100% !important;
}
这可以转换成 Ramda 的说法:
//custom implementation
// (a → b) → [a] → [[b, Number]]
const countBy = curry((mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
});
const arrayFrom = pipe(binary, flip, curry) (Array.from);
const count = pipe (
countBy(identity),
arrayFrom(zipObj(["name", "y"]))
);
console.log(count(['pending', 'pending', 'hired']));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, curry, identity, flip, zipObj, binary} = R; </script>
有了这个,您不仅可以对字符串进行分组,还可以对任何数据类型进行分组,因为映射将保留放入的任何数据:
//custom implementation
// (a → b) → [a] → [[b, Number]]
const countBy = curry((mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
});
const arrayFrom = pipe(binary, flip, curry) (Array.from);
const count = pipe (
countBy(identity),
arrayFrom(zipObj(["name", "y"]))
);
console.log(" --- numbers --- ");
console.log(count([1, 2, "1", 2]));
console.log(" --- objects --- ");
const o1 = {foo: 1};
const o2 = {foo: 2};
const o3 = {foo: 1};
console.log(count([o1, o2, o3, o2]));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, curry, identity, flip, zipObj, binary} = R; </script>
同样,这个实现可能是不需要的。但在极少数情况下可能会引起兴趣。
我使用 Ramda 做了一个解析函数,它像一个 charms 一样工作,但我很确定它可以被简化,不幸的是我正在努力克服这个优化
我想将值分组到一个结构中,该结构具有 'name','y' 是计数。例如,如果 'pending' 出现两次, 'hired' 在我的输入中出现一次,那么我想得到你在输出中看到的内容
我写的函数
const aggResumeStatusTest = data =>
reduce(
(acc, elem) => {
if (!isEmpty(acc)) {
const indexInArray = findIndex(propEq('name', elem))(acc);
if (indexInArray !== -1) {
acc[indexInArray].y++;
} else {
acc.push({
name: elem,
y: 1,
});
}
return acc;
}
acc.push({
name: elem,
y: 1,
});
return acc;
},
[],
data,
);
aggResumeStatusTest(['pending', 'pending', 'hired'])
输入
['pending', 'pending', 'hired']
输出
[ { name: 'pending', y: 2 }, { name: 'hired', y: 1 } ]
在此先感谢您的帮助
我不知道这是否算作优化,但您的代码可以简化。
首先,R.groupBy
将所有这些字符串分组。所以你可以从:
['pending', 'pending', 'hired']
收件人:
[['pending', 'pending'], 'hired']
不同之处在于,它 returns 是一个对象,我们只对它的值感兴趣,所以我们使用 R.values
。
然后你所要做的就是映射它并获取它的长度。
所以最后你有:
let countToObj = arr => ({name : R.head(arr), y: arr.length })
R.map(countToObj, R.values(R.groupBy(R.identity, data)));
let countToObj = arr => ({name : R.head(arr), y: arr.length })
let aggResumeStatusTest = data => R.map(countToObj, R.values(R.groupBy(R.identity, data)));
console.log(aggResumeStatusTest(['pending', 'pending', 'hired']));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>
使用 ramda 可以轻松完成此任务,
请看一看 R.countBy
;
const count = R.pipe(
R.countBy(R.identity),
R.toPairs,
R.map(([name, y]) => ({ name, y })),
)
// ====
const data = ['pending', 'pending', 'hired'];
console.log(
count(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
我喜欢将这些问题视为一系列转换,并加入 pipe
或 compose
。
const count = pipe (
countBy (identity),
toPairs,
map (zipObj (['name', 'y']))
)
console .log (count (['pending', 'pending', 'hired']))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj} = R </script>
这里我们先用countBy
转换为{pending: 2, hired: 1}
。然后用 toPairs
,我们得到 [['pending', 2], ['hired', 1]]
。最后,我们map
zipObj
将那些数组转换成合适的对象,[{"name": "pending", "y": 2}, {"name": "hired", "y": 1}]
我想展示另一种实现方法。首先使用普通 JavaScript,我们可以对 Map 进行计数,然后将该 map 作为可迭代对象 Array.from
转换为对象:
const countBy = (mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
};
const identity = x => x;
const count = input =>
Array.from(
countBy(identity, input),
([name, y]) => ({name, y})
);
console.log(count(['pending', 'pending', 'hired']));
.as-console-wrapper {
max-height: 100% !important;
}
这可以转换成 Ramda 的说法:
//custom implementation
// (a → b) → [a] → [[b, Number]]
const countBy = curry((mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
});
const arrayFrom = pipe(binary, flip, curry) (Array.from);
const count = pipe (
countBy(identity),
arrayFrom(zipObj(["name", "y"]))
);
console.log(count(['pending', 'pending', 'hired']));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, curry, identity, flip, zipObj, binary} = R; </script>
有了这个,您不仅可以对字符串进行分组,还可以对任何数据类型进行分组,因为映射将保留放入的任何数据:
//custom implementation
// (a → b) → [a] → [[b, Number]]
const countBy = curry((mapping, input) => {
const m = new Map();
for (const item of input) {
const key = mapping(item);
m.set(key, (m.get(key) ?? 0) + 1);
}
return m.entries();
});
const arrayFrom = pipe(binary, flip, curry) (Array.from);
const count = pipe (
countBy(identity),
arrayFrom(zipObj(["name", "y"]))
);
console.log(" --- numbers --- ");
console.log(count([1, 2, "1", 2]));
console.log(" --- objects --- ");
const o1 = {foo: 1};
const o2 = {foo: 2};
const o3 = {foo: 1};
console.log(count([o1, o2, o3, o2]));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, curry, identity, flip, zipObj, binary} = R; </script>
同样,这个实现可能是不需要的。但在极少数情况下可能会引起兴趣。