首页 > 其他分享 >由“交卷”功能引发的思考——对比两个字符串数组的差异

由“交卷”功能引发的思考——对比两个字符串数组的差异

时间:2023-03-25 18:22:57浏览次数:53  
标签:const string 重复 standard answer 数组 字符串 交卷

最近在做一个答题系统,在交卷的时候需要判断客观题的答题情况

客观题的题型有单选题、多选题、判断题

其中判断题可以当做单选题处理,而单选题也可以当做标准答案长度为一的多选题

所以最终只需要实现多选题的判定即可

 

一、需求分析

将标准答案和考生回答分别记为字符串数组 standard 和 answer

经过分析,多选题可能出现的情况有:

1. 完全正确

answer 中的所有元素都能在 standard 中找到,且 answer 和 standard 长度相等

2. 部分正确

answer 中的所有元素都能在 standard 中找到,但 answer 的长度小于 standard 

3. 回答错误

answer 中至少有一个元素不在 standard 中

 

为了处理以上情况,可以设计一个排除 standard 和 answer 中重复项的函数,并基于各自剩下的元素来判断结果

/**
 * 去除两个数组的重复项, 并返回处理后的两个数组
 * ```ts
 * 输入: [ ['A', 'B'], ['A', 'C'] ]
 * 输出: [ ['B'], ['C'] ]
 * ```
 * @param data [string[], string[]]
 * @returns [string[], string[]]
 */
function compareArray(data: [string[], string[]]): [string[], string[]] {
  const [standard, answer] = data || [];
  
  // ...
}

 

 

二、函数实现

这个 compareArray 函数内部逻辑和数组去重的过程很类似

// 关于数组去重的方案可以参考《JavaScript 高性能数组去重》

需要遍历数组 A, 拿每个元素去和数组 B 对比, 如果重复则在两个数组中都删除该元素

 

1. 基础版:

使用 indexOf 在 B 数组中查找重复项

若存在重复项,则将元素置空,最后使用 filter 过滤

不建议使用 splice 删除元素,因为它会修改原数组,不易维护遍历的过程

function compareArray(data: [string[], string[]]): [string[], string[]] {
  const [standard, answer] = data || [];

  // 拷贝原数组
  const _standard = [...standard];
  const _answer = [...answer];

  for (let i = 0; i < _standard.length; i++) {
    const k = _standard[i];
    const answerIndex = _answer.indexOf(k);
    if (answerIndex < 0) continue;
    // 如果存在重复元素, 则将对应的元素标记为空
    _standard[i] = '';
    _answer[answerIndex] = '';
  }

  // 过滤空元素
  return [
    _standard.filter((x) => !!x),
    _answer.filter((x) => !!x),
  ];
}

 

2. 进阶版

上面的基础版使用了 indexOf 来查找重复项,会存在重复遍历的情况

可采用空间换时间的思路,改用对象来判断重复项

另外还可以使用增量存储的方式,记录 standard 中未重复的元素,这样就可以省略最后一步的 filter

function compareArray(data: [string[], string[]]): [string[], string[]] {
  const [standard, answer] = data || [];

  // 用于记录 standard 数组的处理结果(增量存储)
  const _standard: string[] = [];
  // 将 answer 转为对象便于查询, 需要手动删除重复值
  const _answerMap: Record<string, true> = answer.reduce(
    (res, x) => ({ ...res, [x]: true }),
    {},
  );

  for (let i = 0; i < standard.length; i++) {
    const k = standard[i];
    // 如果存在重复值, 则删除 answerMap 中的键
    if (_answerMap[k]) {
      Reflect.deleteProperty(_answerMap, k);
    } else {
      // 如果存在不重复, 则记录到结果数组中
      _standard.push(k);
    }
  }

  return [_standard, Object.keys(_answerMap)];
}

 

 

三、结果判断

文章的开头已经提到,多选题的结果存在这三种情况

/** 答题结果 */
export enum ANSWER_RESULT_ENUM {
  /** 完全正确 */
  CORRECT = '1',
  /** 部分正确 */
  NOTBAD = '2',
  /** 回答错误 */
  WRONG = '3',
}

结合上面的 compareArray 函数,可以这么来判断答题结果:

type AnswerItem = string[];

/** 检查单个问题的答题情况 */
function markingPapers(
  answer: AnswerItem,
  standard: AnswerItem,
): ANSWER_RESULT_ENUM {
  // 未作答
  if (!answer?.length) {
    return ANSWER_RESULT_ENUM.WRONG;
  }

  const [_answer, _standard] = compareArray([answer, standard]);

  // 完全正确
  if (!_standard.length && !_answer.length) {
    return ANSWER_RESULT_ENUM.CORRECT;
  }
  // 部分正确
  if (!_answer.length && _standard.length > 0) {
    return ANSWER_RESULT_ENUM.NOTBAD;
  }
  // 回答错误
  return ANSWER_RESULT_ENUM.WRONG;
}

 

标签:const,string,重复,standard,answer,数组,字符串,交卷
From: https://www.cnblogs.com/wisewrong/p/17251501.html

相关文章

  • PHP二维数组排序|PHP二维数组去重
    二维数组排序functionarray_sort($arr,$keys,$order=0){ if(!is_array($arr)){ returnfalse; } $keysvalue=array(); foreach($arras$key=>$val){......
  • hdu-4630(树状数组)
    题目:Lifeisagame,andyouloseit,soyousuicide.Butyoucannotkillyourselfbeforeyousolvethisproblem:Givenyouasequenceofnumbera1,a2,...,an.T......
  • go语言int64整型转字符串
    go语言中string(int)会把int当成UTF-8的Unicode值,转换成对应的字符,标准库strconv是专门用来实现基本数据类型和其字符串表示的相互转换。packagemainimport( "fmt" "s......
  • HJ29_字符串加解密_模拟
    思路:根据加解密规则,使字符串加解密后输出。这是初始理解,编码起来较麻烦。查看高赞题解后,学到一种新思路关于加解密:最佳方法是通过通过设计加解密表,代码比较简单,通过列表in......
  • 数组模拟双向列表 洛谷 P1160 队列安排
    题目描述一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:1.先将1号同学安排进队列,这时队列中只有他一个人;2.2~N号同学依次入列,编号为i的同学入列方式......
  • shell判断字符串结尾
    下面围绕“判断字符串是否以.txt结尾”展开。转变一下也同样适用于“判断字符串是否以.txt开头”。通用的方法#方法一、使用grep命令#!/bin/shstr="/path/to/foo.tx......
  • 实验2 字符串和列表
    实验任务1task.py实验源码:x='nbaFIFA'print(x.upper())print(x.lower())print(x.swapcase())print()x='abc'print(x.center(10,'*'))print(x.ljust(1......
  • 优美字符串
    0036:优美字符串查看提交统计提问总时间限制: 1000ms 内存限制: 65536kB描述对于给定的两个字符串,我们将要做的是将它们拼接起来,拼接成一个“优美”的字符串,那么什么样的......
  • 数组
    目录1.数组概念:2.数组的定义格式一:格式二:详解:注意点:3.数组的静态初始化完整格式:格式详解:注意点:简化格式:练习1:练习2:练习3:4.地址值5.数组元素访问格式:作用:代码示例:6.索引索......
  • 代码随想录Day9-Leetcode28. 实现 strStr(),459.重复的子字符串
    28.实现strStr()这题之前写过,而且印象深刻的是细节很多,所以这边是看完以前的代码,再写的(几乎是在背代码了hhh)甚至这样,next[0]=-1,和j开始匹配子串是没初始化成......