0

We're using ramda in our project and I do have this data structures and I need to do following thing:

For each set check if the submittedCheckboxes are within it and isolate them to new array so I can know if the valid_amount amount of checkboxes set to true isn't exceeded.

In example below it should throw error indicating id of set #1, as the two of submittedCheckboxes have value: true where the set specifies valid_amount: [1], but set #2 should be fine as the valid_amount options are either 1 or 2, (valid_amount: [1,2]). The last set should accept every amount of checked checkboxes belonging to it.

const sets = [
  {id: 1, checkboxes: [{id: 10}, {id: 20}], valid_amount: [1]},
  {id: 2, checkboxes: [{id: 30}, {id: 40}], valid_amount: [1,2]},
  {id: 3, checkboxes: [{id: 50}, {id: 60}, {id: 70}, {id: 80}], valid_amount: [1,2,3,4]},
];

const submittedCheckboxes = [
  {id: 10, value: true},
  {id: 20, value: true},
  {id: 30, value: true},
  {id: 40, value: true},
  {id: 50, value: true},
  {id: 60, value: false},
  {id: 70, value: true},
  {id: 80, value: false},
];

2 Answers 2

1

const sets = [
	{id: 1, checkboxes: [{id: 10}, {id: 20}], valid_amount: [1]},
	{id: 2, checkboxes: [{id: 30}, {id: 40}], valid_amount: [1,2]},
	{id: 3, checkboxes: [{id: 50}, {id: 60}, {id: 70}, {id: 80}], valid_amount: [1,2,3,4]},
];

const submittedCheckboxes = [
	{id: 10, value: true},
	{id: 20, value: true},
	{id: 30, value: true},
	{id: 40, value: true},
	{id: 50, value: true},
	{id: 60, value: false},
	{id: 70, value: true},
	{id: 80, value: false},
];
console.log(sets.map(valid));

function valid(set) {
	return set.valid_amount.includes(set.checkboxes.filter(checkbox => submittedCheckboxes.find(set=>set.id === checkbox.id).value).length)
}

Sign up to request clarification or add additional context in comments.

Comments

0

I think it would make sense to reprocess your data first:

Set

  1. checkboxes don’t need to be a list of objects (e.g. [{id:1},{id:2}]). It can simply be a list of ids (e.g. [1,2])
  2. I’m not sure there’s much point in listing all accepted amounts. Just specify the maximum value each amount can have

So transform:

{id: 2, checkboxes: [{id: 30}, {id: 40}], valid_amount: [1,2]},

into:

{id: 2, checkboxes: [30, 40], max_amount: 2}

Here’s a function for it:

const transformSet = set => ({
  id: set.id,
  checkboxes: map(prop('id'), set.checkboxes),
  max_amount: last(set.valid_amount)
});

Checkboxes

It seems (correct me if I’m wrong) that you only care about the objects for which value is set to true. In this case I’d would remove those for which value is set to false and keep only the ids.

So transform

[
  {id: 10, value: true},
  {id: 20, value: true},
  {id: 30, value: true},
  {id: 40, value: true},
  {id: 50, value: true},
  {id: 60, value: false},
  {id: 70, value: true},
  {id: 80, value: false},
]

into:

[10, 20, 30, 40, 50, 70]

Here’s a function for it:

const transformCheckboxes = into([], compose(
  reject(propEq('value', false)),
  map(prop('id'))
));

Why?

Let’s take set #1, finding whether an answer has been submitted can be as simple as finding the intersection of two arrays:

intersection([10, 20], [10, 20, 30, 40, 50, 70]) //=> [10, 20]

Then you need to make sure that the length of the array isn’t greater than the maximum amount for that set:

const selectCheckboxes = curry((checkboxes, set) =>
  pipe(intersection, length, gte(set.max_amount))
   (set.checkboxes, checkboxes));

Now you can iterate over your sets and you return the first set for which selectCheckboxes doesn’t return true. (Notice the use of complement(selectCheckboxes):

const findError = useWith(find, [
  compose(complement(selectCheckboxes), transformCheckboxes),
  map(transformSet)]);

const {curry, into, intersection, length, gte, map, prop, reject, last, useWith, find, compose, propEq, complement, pipe} = R;

const sets = [
  {id: 1, checkboxes: [{id: 10}, {id: 20}], valid_amount: [1]},
  {id: 2, checkboxes: [{id: 30}, {id: 40}], valid_amount: [1,2]},
  {id: 3, checkboxes: [{id: 50}, {id: 60}, {id: 70}, {id: 80}], valid_amount: [1,2,3,4]},
];

const submittedCheckboxes = [
  {id: 10, value: true},
  {id: 20, value: true},
  {id: 30, value: true},
  {id: 40, value: true},
  {id: 50, value: true},
  {id: 60, value: false},
  {id: 70, value: true},
  {id: 80, value: false},
];

const transformSet = set => ({
  id: set.id,
  checkboxes: map(prop('id'), set.checkboxes),
  max_amount: last(set.valid_amount)
});

const transformCheckboxes = into([], compose(
  reject(propEq('value', false)),
  map(prop('id'))
));


const selectCheckboxes = curry((checkboxes, set) =>
  pipe(intersection, length, gte(set.max_amount))
   (set.checkboxes, checkboxes));


const findError = useWith(find, [
  compose(complement(selectCheckboxes), transformCheckboxes),
  map(transformSet)]);

console.log(

  findError(submittedCheckboxes, sets)
  
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.