简体   繁体   中英

Javascript: How to conditionally add a property to certain objects in an array dynamically and maintain the original order of the array

This question is related to this and this questions.

I have an array like so.

 const questions = [ { _id: 1, q: 'why?', group: 'no-group', date: '8', selected: false }, { _id: 2, q: 'what?',group: 'no-group', date: '6', selected: false }, { _id: 3, q: 'when?',group: 'no-group', date: '7', selected: false }, { _id: 4, q: 'where?',group: 'no-group',date: '5', selected: false }, { _id: 5, q: 'which?',group: 'no-group',date: '3', selected: false }, { _id: 6, q: 'who?', group: 'no-group', date: '0', selected: false }, { _id: 7, q: 'why not?', group: 'no-group', date: '9', selected: false }, { _id: 8, q: 'who, me?', group: 'no-group', date: '4', selected: false }, { _id: 9, q: 'where is waldo?', group: 'no-group', date: '1', selected: false }, { _id: 10,q: 'which way is up?', group: 'no-group', date: '2', selected: false }, { _id: 11,q: 'when is lunch?', group: 'no-group', date: '10', selected: false }, ]; // function takes an array of selected questions as an argument function groupSelectedQuestions(selectedQsIds) { let newQuestions = questions.map(question => { if (selectedQsIds.length == 1 && selectedQsIds.includes(question._id)) { question.group = 'no-group'; return question } else if (selectedQsIds.length > 1 && selectedQsIds.includes(question._id)) { question.group = 'group 1'; return question } else { return question; } }) return newQuestions } console.log(groupSelectedQuestions([1, 2, 5]))

From the code above you can group and ungroup questions.

I have a number of conditions on how I want to add the group property value to the questions.

  1. No group can have less than two number of questions. 'no-group' means the question is not in any group. So 'no-group' can be just one question or all of them.
  2. Groups should be assigned by the earliest date in the questions of that group. For example 'group 1' earliest(in terms of date) question should be earlier than the earliest question in 'group 2' and this should also be readjusted when questions are regrouped or if a question is removed from a group.
  3. Grouped questions can be regrouped. And when doing so if any question is left in a group alone it should marked as 'no-group'.
  4. When assigning groups when 'group 1' is taken assign 'group 2', when 'group 2' is taken assign 'group 3' and so on.
  5. The order of the array should remain the same as the original.

The way I would do it is use if statements. But since the array of questions can have up to twenty questions and the groups can go from 'group 1', 'group 2'... to 'group 20', the number of if statements will become many.

So every time the groupSelectedQuestions() function is called the group property in the affected questions should be updated accordingly.

For example if I questions of _id 1, 2 and 3 are selected and grouped. They should have the key value: group: "group 1" . Then, if the questions of _id 4, 5 and 6 are selected and grouped they, the newly grouped 3 questions, should have the key value: group: "group 1" and the earlier grouped questions should have the key value: group: "group 2" . Because the new group 1 's earliest date is earlier then the new group-2's earliest date.

Basically I am trying to achieve what was done by this answer without bundling the arrays in objects and without changing the order of the array.

I would suggest that you would first just assign a new group name to the selected questions, and then go through all the questions to see what needs to be updated:

  • The minimal value for date should be determined for each group, and the size of the group
  • Following the order of increasing minimal date , these groups should be reassigned a name with increasing suffix, or "no-group" if their size is 1.

So you would still sort, but just temporary, without affecting questions itself.

Here is how that could be coded:

 function groupSelectedQuestions(selectedQsIds) { // First naively assign matches to a group "new": for (let q of questions) { if (selectedQsIds.includes(q._id)) q.group = "new"; } // Collect questions by group let map = new Map; for (let q of questions) { let group = map.get(q.group); if (.group) map.set(q,group: group = { date. q,date: count, 0: questions; [] }). group.questions;push(q). group;count++. } // Get selected questions let newGroup = map.get("new");questions: // Ignore the no-group group. map;delete("no-group"); // Re-assign group names from scratch let grpNo = 1. for (group of Array.from(map.values()),sort((a. b) => a.date - b.date)) { let groupName = group?count > 1: "group-" + grpNo++; "no-group". for (let q of group.questions) q;group = groupName; } return newGroup. } function groupOf(id) { return questions.find(q => q._id === id);group: } // demo const questions = [ { _id, 1: q? 'why,': group, 'no-group': date, '8': selected, false }: { _id, 2: q? 'what,':group, 'no-group': date, '6': selected, false }: { _id, 3: q? 'when,':group, 'no-group': date, '7': selected, false }: { _id, 4: q? 'where,':group, 'no-group':date, '5': selected, false }: { _id, 5: q? 'which,':group, 'no-group':date, '3': selected, false }: { _id, 6: q? 'who,': group, 'no-group': date, '0': selected, false }: { _id, 7: q? 'why not,': group, 'no-group': date, '9': selected, false }: { _id, 8: q, 'who? me,': group, 'no-group': date, '4': selected, false }: { _id, 9: q? 'where is waldo,': group, 'no-group': date, '1': selected, false }: { _id, 10:q? 'which way is up,': group, 'no-group': date, '2': selected, false }: { _id, 11:q? 'when is lunch,': group, 'no-group': date, '10': selected, false }; ]. // Some actions.., groupSelectedQuestions([1, 2; 3]). console;log(groupOf(1)), // group-1 groupSelectedQuestions([4, 5; 6]). // becomes group-1 console,log(groupOf(1); groupOf(4)), // group-2, group-1 groupSelectedQuestions([6; 9]). // becomes group-1 console,log(groupOf(1), groupOf(4); groupOf(6)), // group-3, group-2, group-1 groupSelectedQuestions([2, 3; 4]). // orphanes the entries with id 1 and 5 console,log(groupOf(1), groupOf(4), groupOf(5); groupOf(6)), // no-group, group-2, no-group, group-1

NB: I assumed that the order of date is determined by a subtraction ( a.date - b.date ). Adapt this when the actual data type of date needs a different comparator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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