简体   繁体   English

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

[英]How to sort object with ramda js

I want to sort the following object, 我想对以下对象进行排序,

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'
}

I am implementing a form with nested check boxes who's value can be 'Y' or 'N'. 我正在实现带有嵌套复选框的表单,其值可以是“ Y”或“ N”。 I want to capture only the 'Y' check boxes, and if all of the child check boxes are 'Y', I want to discard them and get only parent checkbox. 我只想捕获“ Y”复选框,并且如果所有子复选框都为“ Y”,则我想丢弃它们并仅获得父复选框。 Above is the object which has all the check box values. 上面是具有所有复选框值的对象。 I want the object to be sorted to: 我希望将对象排序为:

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

My code so far looks like this: 到目前为止,我的代码如下所示:

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"}}

You're close with your attempt, you just need to recursively call map for each object that it finds in the values of the object. 您的尝试已接近尾声,您只需要为在对象值中找到的每个对象递归调用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> 

I have a partial solution, and no time at the moment to take the next step. 我有一个局部解决方案,目前没有时间采取下一步措施。 It essentially filters out any values that are not 'Y' s. 实际上,它会过滤掉所有不是'Y'的值。 You should then be able to add another step to slim this down by recursively replacing values which are objects containing only 'Y' values with just '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)) 

This solution doesn't use Ramda. 此解决方案不使用Ramda。 I'm one of the founders of Ramda, and a big fan of the library, but I don't see Ramda offering much help here, only a few minor clean-ups. 我是Ramda的创始人之一,也是图书馆的忠实拥护者,但是我没有看到Ramda在这里提供很多帮助,只是进行了一些小小的清理工作。

Here is a slightly different approach that (afaict) produces the same result as Scott Christopher's answer: 这是一种略有不同的方法,(确实)产生的结果与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