Survey grid
MediumOnline Assessment
Turn the raw rows of a customer survey into a results grid with one row per question and one column per answer.
Each response is a string "respondent,question,answer". All three fields may have spaces around them, which are ignored. Respondent ids and answers are compared ignoring case, and so are question names (q3a and Q3A are the same question). A question name is the letter Q, then an integer without leading zeros, then optionally one lowercase letter (Q3, Q3a, Q12).
Rules:
- A respondent may answer a question several times. Only their last response to that question (the latest one in the list) counts.
- If that last response has an empty answer, the respondent withdrew their answer: it does not count at all.
- The
scaleis the list of accepted answers, in the order of the columns. An answer that matches none of them (ignoring case) counts in an extra last column called "other". - Only questions that have at least one counted answer get a row.
Input: responses, a list of strings in the format above, and scale, a list of distinct, non-empty answer labels in lowercase.
Output: a list of rows. Each row is a list: first the question written in uppercase and without spaces ("Q3A"), then one count for each label of scale in order, then the count of "other" answers. Order the rows by question number, then by the optional letter (a question with no letter comes before one with a letter: Q3, Q3A, Q3B, Q12). If there are no rows, return [].
Example 1
- Input:
- [["u1,Q1,agree","u2,Q1,Agree ","u3,Q1,disagree","u1,Q2,neutral","u2,Q10,agree","u3,Q2,maybe"],["agree","neutral","disagree"]]
- Output:
- [["Q1",2,0,1,0],["Q2",0,1,0,1],["Q10",1,0,0,0]]
- Explanation
- Q1 gets two agrees (case and spaces ignored) and one disagree. Q2 has one neutral and "maybe", which is not on the scale, so it counts as other. Q10 sorts after Q2 because question numbers are compared as numbers.
Example 2
- Input:
- [["Ann,Q1,agree","ann,Q1,neutral","BOB,Q1,agree","bob ,Q1,","cy,Q2,agree","cy,Q2,","dee,Q3,disagree"],["agree","neutral","disagree"]]
- Output:
- [["Q1",0,1,0,0],["Q3",0,0,1,0]]
- Explanation
- ann changes her mind on Q1, so only her last answer (neutral) counts. bob withdraws his Q1 answer with an empty one, so Q1 has just ann's neutral. cy's only Q2 answer is withdrawn, so Q2 has no counted answers and gets no row.
Example 3
- Input:
- [["a,Q3b,agree","a,Q3,agree","b,q3a,neutral","b,Q2,Disagree","c,Q11,x","c,Q3b,agree"],["agree","neutral","disagree"]]
- Output:
- [["Q2",0,0,1,0],["Q3",1,0,0,0],["Q3A",0,1,0,0],["Q3B",2,0,0,0],["Q11",0,0,0,1]]
- Explanation
- Q3 comes before Q3A and Q3B, and all of them before Q11. Q3B has two agrees (the first answer from a, and c's). b's lowercase q3a is the same question as Q3A. The answer "x" is not on the scale, so Q11 has one other.
Constraints
0 <= responses.length <= 400,1 <= scale.length <= 6- Question numbers are between 1 and 99; fields contain no commas
- Respondent ids are non-empty after trimming