当前位置: 首页 > news >正文

【ES6】使用Set和Map进行全组合判断

判断数据集是否为全组合关系

例如下列表格,字段1包含(甲、乙)值,字段2包含(a、b)值,字段3包含(1、2、3)值,每种组合情况都可以在数据集的行记录中找到有且仅有的一条

字段1字段2字段3
a1
a2
a3
b1
b2
b3
a1
a2
a3
b1
b2
b3

要求函数输入以下格式数据,输出布尔值。

const inputData = [{ "字段1": "甲", "字段2": "a", "字段3": 1 },{ "字段1": "甲", "字段2": "a", "字段3": 2 },{ "字段1": "甲", "字段2": "a", "字段3": 3 },{ "字段1": "甲", "字段2": "b", "字段3": 1 },{ "字段1": "甲", "字段2": "b", "字段3": 2 },{ "字段1": "甲", "字段2": "b", "字段3": 3 },{ "字段1": "乙", "字段2": "a", "字段3": 1 },{ "字段1": "乙", "字段2": "a", "字段3": 2 },{ "字段1": "乙", "字段2": "a", "字段3": 3 },{ "字段1": "乙", "字段2": "b", "字段3": 1 },{ "字段1": "乙", "字段2": "b", "字段3": 2 },{ "字段1": "乙", "字段2": "b", "字段3": 3 },
]

实现

1.遍历inputData并罗列出每个字段对应的全部可能值:

const inputData = [{ "字段1": "甲", "字段2": "a", "字段3": 1 },{ "字段1": "甲", "字段2": "a", "字段3": 2 },{ "字段1": "甲", "字段2": "a", "字段3": 3 },{ "字段1": "甲", "字段2": "b", "字段3": 1 },{ "字段1": "甲", "字段2": "b", "字段3": 2 },{ "字段1": "甲", "字段2": "b", "字段3": 3 },{ "字段1": "乙", "字段2": "a", "字段3": 1 },{ "字段1": "乙", "字段2": "a", "字段3": 2 },{ "字段1": "乙", "字段2": "a", "字段3": 3 },{ "字段1": "乙", "字段2": "b", "字段3": 1 },{ "字段1": "乙", "字段2": "b", "字段3": 2 },{ "字段1": "乙", "字段2": "b", "字段3": 3 },
]function isFullCombination(data) {if (data.length === 0) {return false}const fieldMap = new Map() // 字段映射对象const keys = Object.keys(data[0]) // 获取数据集字段名for (const item of data) {for (const key of keys) {const value = item[key]let valueSet = fieldMap.get(key) // 尝试获取Map中字段对应的值集合if (!valueSet) {valueSet = new Set() // 使用Set实现去重fieldMap.set(key, valueSet)}valueSet.add(value)}}console.log(fieldMap);
}console.log(isFullCombination(inputData));
Map(3) {'字段1' => Set(2) { '甲', '乙' },'字段2' => Set(2) { 'a', 'b' },'字段3' => Set(3) { 1, 2, 3 }
}

2.那么全组合情况下,inputData数组的长度应为 2*2*3,也就是12,对长度进行判断:

function isFullCombination(data) {if (data.length === 0) {return false}const fieldMap = new Map()const keys = Object.keys(data[0]) for (const item of data) {for (const key of keys) {const value = item[key]let valueSet = fieldMap.get(key) if (!valueSet) {valueSet = new Set() fieldMap.set(key, valueSet)}valueSet.add(value)}}const length = [...fieldMap].reduce((s, [, v]) => (s *= v.size), 1)return length === data.length // 对比length
}

3.除了length还需要考虑元素是否重复,如果对inputData进行去重处理,会提高时间复杂度,所以在已有的循环中顺便进行是否重复的判断即可。将所有值拼接为字符串并存储到集合中,对比字符串是否相同。

注意:拼接后的字符存储到集合中,因为需要判断集合中是否已有重复的字符串,所以使用Set存储,因为Set.has时间复杂度为O(1),而Array判断时间复杂度为O(n)。

function isFullCombination(data) {if (data.length === 0) {return false}const fieldMap = new Map() const keys = Object.keys(data[0]) const combinationSet = new Set() // 组合情况集合for (const item of data) {let combination = ""for (const key of keys) {const value = item[key]let valueSet = fieldMap.get(key) if (!valueSet) {valueSet = new Set() fieldMap.set(key, valueSet)}valueSet.add(value)combination += value}if (combinationSet.has(combination)) {return false // 如果重复,则说明不是全组合}combinationSet.add(combination) // 如果不存在,则添加到集合中}console.log(combinationSet)const length = [...fieldMap].reduce((s, [, v]) => (s *= v.size), 1)return length === data.length
}

4.但是还存在问题,那就是字段值重复,如下面这个inputData:

const inputData = [{ a: "-", b: "-" },{ a: "-", b: "--" },{ a: "--", b: "-" },{ a: "--", b: "--" },
]

目前无法判断,需要在存入映射对象时手动将值存为唯一值,这里通过自增的n作为唯一标识,然后使用每个字段对应的唯一标识拼接字符串。

function isFullCombination(data) {if (data.length === 0) {return false}const fieldMap = new Map() const keys = Object.keys(data[0]) const combinationSet = new Set()const valueMap = new Map() // 记录每个字段的值集合let n = 1for (const item of data) {let combination = ""for (const key of keys) {const value = item[key]let valueSet = fieldMap.get(key)if (!valueSet) {valueSet = new Set() fieldMap.set(key, valueSet)}valueSet.add(value)let num = valueMap.get(value) // 尝试获取Map中字段对应的值if (!num) {num = n++valueMap.set(value, num) }combination += num+''}console.log(valueMap)if (combinationSet.has(combination)) {return false }combinationSet.add(combination) }const length = [...fieldMap].reduce((s, [, v]) => (s *= v.size), 1)return length === data.length
}

整体实现代码

const inputData = [{ 字段1: "甲", 字段2: "a", 字段3: 1 },{ 字段1: "甲", 字段2: "a", 字段3: 2 },{ 字段1: "甲", 字段2: "a", 字段3: 3 },{ 字段1: "甲", 字段2: "b", 字段3: 1 },{ 字段1: "甲", 字段2: "b", 字段3: 2 },{ 字段1: "甲", 字段2: "b", 字段3: 3 },{ 字段1: "乙", 字段2: "a", 字段3: 1 },{ 字段1: "乙", 字段2: "a", 字段3: 2 },{ 字段1: "乙", 字段2: "a", 字段3: 3 },{ 字段1: "乙", 字段2: "b", 字段3: 1 },{ 字段1: "乙", 字段2: "b", 字段3: 2 },{ 字段1: "乙", 字段2: "b", 字段3: 3 },
]// const inputData = [
//   { a: "-", b: "-" },
//   { a: "-", b: "--" },
//   { a: "--", b: "-" },
//   { a: "--", b: "--" },
// ]function isFullCombination(data) {if (data.length === 0) {return false}const fieldMap = new Map() // 字段映射对象const keys = Object.keys(data[0]) // 获取数据集字段名const combinationSet = new Set() // 组合情况集合const valueMap = new Map() // 记录每个字段的值集合let n = 1for (const item of data) {let combination = ""for (const key of keys) {const value = item[key]let valueSet = fieldMap.get(key) // 尝试获取Map中字段对应的值集合if (!valueSet) {valueSet = new Set() // 使用Set实现去重fieldMap.set(key, valueSet)}valueSet.add(value)let num = valueMap.get(value) // 尝试获取Map中字段对应的值if (!num) {num = n++valueMap.set(value, num)}combination += num + ""}console.log(combination)if (combinationSet.has(combination)) {return false // 如果重复,则说明不是全组合}combinationSet.add(combination) // 如果不存在,则添加到集合中}const length = [...fieldMap].reduce((s, [, v]) => (s *= v.size), 1)return length === data.length
}console.log(isFullCombination(inputData))

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Java微服务生态系统构建指南
  • 《PostgreSQL 中通过函数实现不确定列的数据更新操作》
  • MYSQL 删除一个字段前,判断字段是否存在
  • 高级Web安全技术(第二篇)
  • C#学习笔记16:串口上位机数据绘图助手Plotter的开发
  • 如何学好uni-app
  • C# POST请求 各种实现方法梳理
  • 004集——静态常量和动态常量——C#学习笔记
  • 【通信原理】matlab中qammod的介绍
  • 作业8.9
  • ES架构模型
  • AI大模型赋能开发者|海云安创始人谢朝海受邀在ISC.AI 2024大会就“大模型在软件开发安全领域的应用”主题发表演讲
  • Java内存模型-清晰剖析
  • 【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)
  • Spring中dbUtil的概念和搭建使用
  • Android优雅地处理按钮重复点击
  • css属性的继承、初识值、计算值、当前值、应用值
  • Git初体验
  • HTTP那些事
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • 闭包,sync使用细节
  • 手机端车牌号码键盘的vue组件
  • 通信类
  • 小程序 setData 学问多
  • No resource identifier found for attribute,RxJava之zip操作符
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • ​补​充​经​纬​恒​润​一​面​
  • #java学习笔记(面向对象)----(未完结)
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (2)STL算法之元素计数
  • (LeetCode) T14. Longest Common Prefix
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (译) 函数式 JS #1:简介
  • (转)详解PHP处理密码的几种方式
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .Net Core 微服务之Consul(二)-集群搭建
  • .NET 服务 ServiceController
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET 漏洞分析 | 某ERP系统存在SQL注入
  • .Net 中Partitioner static与dynamic的性能对比
  • .NET建议使用的大小写命名原则
  • .py文件应该怎样打开?
  • @angular/cli项目构建--Dynamic.Form
  • @angular/cli项目构建--http(2)
  • @media screen 针对不同移动设备
  • @RestControllerAdvice异常统一处理类失效原因
  • []Telit UC864E 拨号上网
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [2018][note]用于超快偏振开关和动态光束分裂的all-optical有源THz超表——
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [Algorithm][综合训练][kotori和气球][体操队形][二叉树中的最大路径和]详细讲解