繁体   English   中英

如何使用Ramda JS对对象进行排序

[英]How to sort object with ramda js

我想对以下对象进行排序,

const form = {
A_ALL: {A1_ALL: { A1_ONE: 'Y', A2_TWO: 'Y', A3_THREE: 'Y'}, A2: {A2_FOUR: 'Y', A2_FIVE: 'N', A2_SIX: 'Y'}, A3: 'Y', A4: 'N'},
B_ALL: {B1_ALL: { B1_ONE: 'Y', B1_TWO: 'Y', B1_THREE: 'Y'}, B2: {B2_FOUR: 'Y', B2_FIVE: 'Y', B2_SIX: 'Y'}, B3: 'Y', B4: 'Y'},
C_ALL: {XX: 'Y', YY:'Y'},
D: 'Y',
E: 'N'
}

我正在实现带有嵌套复选框的表单,其值可以是“ Y”或“ N”。 我只想捕获“ Y”复选框,并且如果所有子复选框都为“ Y”,则我想丢弃它们并仅获得父复选框。 上面是具有所有复选框值的对象。 我希望将对象排序为:

{
A_ALL: {A1_ALL: 'Y', A2: {A2_FOUR: 'Y', A2_SIX: 'Y'}, A3: 'Y'},
B_ALL : 'Y',
C: 'Y',
D: 'Y'
}

到目前为止,我的代码如下所示:

const FORM = ({ A1_ALL: { a: 'Y', b: 'Y', c: 'Y' }, B1_ALL: { a: 'Y', b: 'Y', c: 'N' }, C1_ALL: { a: 'Y', b: 'Y', c: 'Y' }, }) 
const eY = equals('Y') 
const isSelected = compose(all(eY), values) 
const groupValue = when(isSelected, always('Y')); 
const formValue = map(groupValue) formValue(FORM) Result is {A1_ALL: "Y", C1_ALL: "Y", B1_ALL: {a: "Y", b: "Y", c: "N"}}

您的尝试已接近尾声,您只需要为在对象值中找到的每个对象递归调用map

 const form = { A_ALL: {A1_ALL: { A1_ONE: 'Y', A2_TWO: 'Y', A3_THREE: 'Y'}, A2: {A2_FOUR: 'Y', A2_FIVE: 'N', A2_SIX: 'Y'}, A3: 'Y', A4: 'N'}, B_ALL: {B1_ALL: { B1_ONE: 'Y', B1_TWO: 'Y', B1_THREE: 'Y'}, B2: {B2_FOUR: 'Y', B2_FIVE: 'Y', B2_SIX: 'Y'}, B3: 'Y', B4: 'Y'}, C_ALL: {XX: 'Y', YY:'Y'}, D: 'Y', E: 'N' } const eY = R.equals('Y') const isSelected = R.compose(R.all(eY), R.values) const groupValue = R.when(isSelected, R.always('Y')) const fn = objOrString => R.pipe( R.unless(R.is(String), R.map(fn)), R.unless(R.is(String), groupValue), R.unless(R.is(String), R.filter(R.either(R.is(Object), R.equals('Y')))) )(objOrString) console.log(fn(form)) 
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script> 

我有一个局部解决方案,目前没有时间采取下一步措施。 实际上,它会过滤掉所有不是'Y'的值。 然后,您应该能够通过递归替换仅包含'Y'值的对象'Y'值而仅使用'Y'来减少这一步。

 const form = { A_ALL: {A1_ALL: { A1_ONE: 'Y', A2_TWO: 'Y', A3_THREE: 'Y'}, A2: {A2_FOUR: 'Y', A2_FIVE: 'N', A2_SIX: 'Y'}, A3: 'Y', A4: 'N'}, B_ALL: {B1_ALL: { B1_ONE: 'Y', B1_TWO: 'Y', B1_THREE: 'Y'}, B2: {B2_FOUR: 'Y', B2_FIVE: 'Y', B2_SIX: 'Y'}, B3: 'Y', B4: 'Y'}, C_ALL: {XX: 'Y', YY:'Y'}, D: 'Y', E: 'N' } const isObject = s => Object.prototype.toString.call(s) == '[object Object]' const isArray = s => Object.prototype.toString.call(s) == '[object Array]' const collect = pairs => pairs.reduce( (a, [k, v]) => ({...a, [k]: isArray(v) ? collect(v) : v}), {} ) const spread = val => obj => Object.entries(obj) .filter(([k, v]) => v == val || isObject(v)) .map(([k, v]) => isObject(v) ? [k, spread(val)(v)] : [k, v]) const findMatchingKeys = (val, obj) => collect(spread(val)(obj)) console.log(findMatchingKeys('Y', form)) 

此解决方案不使用Ramda。 我是Ramda的创始人之一,也是图书馆的忠实拥护者,但是我没有看到Ramda在这里提供很多帮助,只是进行了一些小小的清理工作。

这是一种略有不同的方法,(确实)产生的结果与Scott Christopher的答案相同:

 // Ramda doesn't support folding objects, so we have to define this here // :: Monoid m -> (a -> m) -> StrMap a -> m const foldMap = M => f => o => R.keys(o).reduce((p, c) => M.append(p)(f(o[c])), M.empty); // :: Monoid Boolean const And = { empty: true, append: x => y => x && y }; // Each layer of the form can be thought of as a string map, where // a key is mapped to one of the strings "Y" or "N", or to a value // of some given type `a` // :: type ValueOr a = "Y" | "N" | a // :: type FormLayer a = StrMap (ValueOr a) // We can think of a form as an infinite nesting of form layers // :: type Fix f = f (Fix f) // :: type Form = Fix FormLayer // = FormLayer (FormLayer (FormLayer (FormLayer ...))) // Recursion schemes can help us promote a function for operating // on one layer of the structure to a function that operates on an // infinite nesting of layers // :: Functor f -> (fa -> a) -> Fix f -> a const cata = F => alg => { const rec = x => alg(F.map(rec)(x)); return rec; }; // It's useful to factor repeated case analysis into a pattern const ValOr = { Y: "Y", N: "N", Other: x => x, match: ({ Y, N, Other }) => v => v === "Y" ? Y : v === "N" ? N : Other(v), map: f => ValOr.match({ Y, N, Other: f }) }; const { Y, N, Other } = ValOr; // :: Functor FormLayer const FormLayer = { map: f => R.map(ValOr.map(f)) }; // :: ValueOr _ -> Boolean const isY = ValOr.match({ Y: true, N: false, Other: _ => false }); // :: FormLayer _ -> Boolean const allYs = foldMap(And)(isY); // :: Form -> ValueOr Form const squashYs = cata(FormLayer)(o => allYs(o) ? Y : Other(o)); // :: ValueOr _ -> Boolean const isntN = ValOr.match({ Y: true, N: false, Other: _ => true }); // :: Form -> Form const filterNs = cata(FormLayer)(R.filter(isntN)); // :: Form -> ValueOr Form const f = R.pipe( // Squash Y-only objects recursively squashYs, // If the top level result is still a form, filter out the "N"s recursively ValOr.match({ Y, N, Other: filterNs }) ); // :: Form const form = { A_ALL: { A1_ALL: { A1_ONE: "Y", A2_TWO: "Y", A3_THREE: "Y" }, A2: { A2_FOUR: "Y", A2_FIVE: "N", A2_SIX: "Y" }, A3: "Y", A4: "N" }, B_ALL: { B1_ALL: { B1_ONE: "Y", B1_TWO: "Y", B1_THREE: "Y" }, B2: { B2_FOUR: "Y", B2_FIVE: "Y", B2_SIX: "Y" }, B3: "Y", B4: "Y" }, C_ALL: { XX: "Y", YY: "Y" }, D: "Y", E: "N" }; // :: ValueOr Form const result = f(form); console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM