范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

golang2021数据格式(71)Go语言map的多键索引多个数值条件可以

  在大多数的编程语言中,映射容器的键必须以单一值存在。这种映射方法经常被用在诸如信息检索上,如根据通讯簿的名字进行检索。但随着查询条件越来越复杂,检索也会变得越发困难。下面例子中涉及通讯簿的结构,结构如下:
  //  人员档案
    type Profile struct {
        Name    string    // 名字
        Age     int       // 年龄
        Married bool     // 已婚
    }
  并且准备好了一堆原始数据,需要算法实现构建索引和查询的过程,代码如下:
  func  main() {
  list  := []*Profile{
            {Name: "张三", Age: 30,  Married: true},
            {Name: "李四", Age:  21},
            {Name: "王麻子", Age:  21},
        }
  buildIndex(list)
  queryData("张三",  30)
    }
  需要用算法实现  buildIndex() 构建索引函数及 queryData() 查询数据函数,查询到结果后将数据打印出来。
   
  下面,分别基于传统的基于哈希值的多键索引和利用  map 特性的多键索引进行查询。
  基于哈希值的多键索引及查询
  传统的数据索引过程是将输入的数据做特征值。这种特征值有几种常见做法:
  将特征使用某种算法转为整数,即哈希值,使用整型值做索引。
  将特征转为字符串,使用字符串做索引。
  数据都基于特征值构建好索引后,就可以进行查询。查询时,重复这个过程,将查询条件转为特征值,使用特征值进行查询得到结果。
   
  基于哈希的传统多键索引和查询的完整代码位于./src/chapter12/classic/classic.go,下面是对各个部分的分析。
   
  1)  字符串转哈希值
  本例中,查询键(classicQueryKey)的特征值需要将查询键中每一个字段转换为整型,字符串也需要转换为整型值,这里使用一种简单算法将字符串转换为需要的哈希值,代码如下:
  func  simpleHash(str string) (ret int) {
  //  遍历字符串中的每一个ASCII字符
        for i := 0; i < len(str); i++  {
            // 取出字符
            c := str[i]
  //  将字符的ASCII码相加
            ret += int(c)
        }
  return
    }
  代码说明如下:
  第 1       行传入需要计算哈希值的字符串。
  第 4       行,根据字符串的长度,遍历这个字符串的每一个字符,以 ASCII 码为单位。
  第 9 行,c       变量的类型为 uint8,将其转为 int 类型并累加。
  哈希算法有很多,这里只是选用一种大家便于理解的算法。哈希算法的选用的标准是尽量减少重复键的发生,俗称"哈希冲撞",即同样两个字符串的哈希值重复率降到最低。
  2) 查询键
  有了哈希算法函数后,将哈希函数用在查询键结构中。查询键结构如下:
  //  查询键
    type classicQueryKey struct {
        Name string  // 要查询的名字
        Age   int     // 要查询的年龄
    }
  //  计算查询键的哈希值
    func (c *classicQueryKey) hash() int {
        // 将名字的Hash和年龄哈希合并
        return simpleHash(c.Name) +  c.Age*1000000
    }
  代码说明如下:
  第 2       行,声明查询键的结构,查询键包含需要索引和查询的字段。
  第 8       行,查询键的成员方法哈希,通过调用这个方法获得整个查询键的哈希值。
  第 10       行,查询键哈希的计算方法:使用 simpleHash() 函数根据给定的名字字符串获得其哈希值。同时将年龄乘以 1000000 与名字哈希值相加。
  哈希值构建过程如下图所示
  3) 构建索引
  本例需要快速查询,因此需要提前对已有的数据构建索引。前面已经准备好了数据查询键,使用查询键获得哈希即可对数据进行快速索引,参考下面的代码:
  //  创建哈希值到数据的索引关系
    var mapper = make(map[int][]*Profile)
  //  构建数据索引
    func buildIndex(list []*Profile) {
  //  遍历所有的数据
        for _, profile := range list {
  //  构建数据的查询索引
            key :=  classicQueryKey{profile.Name, profile.Age}
  //  计算数据的哈希值, 取出已经存在的记录
            existValue :=  mapper[key.hash()]
  //  将当前数据添加到已经存在的记录切片中
            existValue = append(existValue,  profile)
  //  将切片重新设置到映射中
            mapper[key.hash()] =  existValue
        }
    }
  代码说明如下:
  第 2       行,实例化一个 map,键类型为整型,保存哈希值;值类型为 *Profile,为通讯簿的数据格式。
  第 5       行,构建索引函数入口,传入数据切片。
  第 8       行,遍历数据切片的所有数据元素。
  第 11       行,使用查询键(classicQueryKey)来辅助计算哈希值,查询键需要填充两个字段,将数据中的名字和年龄赋值到查询键中进行保存。
  第 14       行,使用查询键的哈希方法计算查询键的哈希值。通过这个值在 mapper       索引中查找相同哈希值的数据切片集合。因为哈希函数不能保证不同数据的哈希值一定完全不同,因此要考虑在发生哈希值重复时的处理办法。
  第 17       行,将当前数据添加到可能存在的切片中。
  第 20       行,将新添加好的数据切片重新赋值到相同哈希的 mapper 中。
  具体哈希结构如下图所示。
  图:哈希结构
  这种多键的算法就是哈希算法。map  的多个元素对应哈希的"桶"。哈希函数的选择决定桶的映射好坏,如果哈希冲撞很厉害,那么就需要将发生冲撞的相同哈希值的元素使用切片保存起来。
  4) 查询逻辑
  从已经构建好索引的数据中查询需要的数据流程如下:
  给定查询条件(名字、年龄)。
  根据查询条件构建查询键。
  查询键生成哈希值。
  根据哈希值在索引中查找数据集合。
  遍历数据集合逐个与条件比对。
  获得结果。
  func  queryData(name string, age int) {
  //  根据给定查询条件构建查询键
        keyToQuery := classicQueryKey{name,  age}
  //  计算查询键的哈希值并查询, 获得相同哈希值的所有结果集合
        resultList :=  mapper[keyToQuery.hash()]
  //  遍历结果集合
        for _, result := range resultList {
  //  与查询结果比对, 确认找到打印结果
            if result.Name == name  && result.Age == age {
                fmt.Println(result)
                return
            }
        }
  //  没有查询到时, 打印结果
        fmt.Println("no found")
  }
  代码说明如下:
  第 1       行,查询条件(名字、年龄)。
  第 4       行,根据查询条件构建查询键。
  第 7       行,使用查询键计算哈希值,使用哈希值查询相同哈希值的所有数据集合。
  第 10       行,遍历所有相同哈希值的数据集合。
  第 13       行,将每个数据与查询条件进行比对,如果一致,表示已经找到结果,打印并返回。
  第 20       行,没有找到记录时,打印 no found。
  利用 map  特性的多键索引及查询
  使用结构体进行多键索引和查询比传统的写法更为简单,最主要的区别是无须准备哈希函数及相应的字段无须做哈希合并。看下面的实现流程。
   
  利用map特性的多键索引和查询的代码位于./src/chapter12/multikey/multikey.go,下面是对各个部分的分析。
   
  1) 构建索引
  代码如下:
  //  查询键
    type queryKey struct {
        Name string
        Age   int
    }
  //  创建查询键到数据的映射
    var mapper = make(map[queryKey]*Profile)
  //  构建查询索引
    func buildIndex(list []*Profile) {
  //  遍历所有数据
        for _, profile := range list {
  //  构建查询键
            key := queryKey{
                Name: profile.Name,
                Age:  profile.Age,
            }
  //  保存查询键
            mapper[key] = profile
        }
    }
  代码说明如下:
  第 2       行,与基于哈希值的查询键的结构相同。
  第 8 行,在       map 的键类型上,直接使用了查询键结构体。注意,这里不使用查询键的指针。同时,结果只有 *Profile 类型,而不是 *Profile       切片,表示查到的结果唯一。
  第 17       行,类似的,使用遍历到的数据的名字和年龄构建查询键。
  第 23       行,更简单的,直接将查询键保存对应的数据。
  2) 查询逻辑
  //  根据条件查询数据
    func queryData(name string, age int) {
  //  根据查询条件构建查询键
        key := queryKey{name, age}
  //  根据键值查询数据
        result, ok := mapper[key]
  //  找到数据打印出来
        if ok {
            fmt.Println(result)
        } else {
            fmt.Println("no  found")
        }
    }
  代码说明如下:
  第 5       行,根据查询条件(名字、年龄)构建查询键。
  第 8       行,直接使用查询键在 map 中查询结果。
  第 12       行,找到结果直接打印。
  第 14       行,没有找到结果打印 no found。
  总结
  基于哈希值的多键索引查询和利用  map 特性的多键索引查询的代码复杂程度显而易见。聪明的程序员都会利用 Go语言的特性进行快速的多键索引查询。
   
  其实,利用 map 特性的例子中的  map 类型即便修改为下面的格式,也一样可以获得同样的结果:
   
  var       mapper = make(map[interface{}]*Profile)
  代码量大大减少的关键是:Go语言的底层会为  map 的键自动构建哈希值。能够构建哈希值的类型必须是非动态类型、非指针、函数、闭包。
  非动态类型:可用数组,不能用切片。
  非指针:每个指针数值都不同,失去哈希意义。
  函数、闭包不能作为       map 的键。

拼夕夕多次暴雷,为何售卖的商品都是好评?拼夕夕售卖的商品为何都是好评不断?为何我们几乎看到任何差评?如下图但在其它平台上,不管是任何商品都会看到差评,拼夕夕的商品真的就可以做到人人满意吗?从某种意义上来说,拼夕夕确实抓住中国移动业务上的死循环本人在2014年预存话费500元开通了国际漫游业务,现在一直住在国外,手机主要用来接收各种验证码,绑定了几张银行卡。不知道什么时候发现处于无服务状态了,经过各种尝试,最终确定是国家时代在进步,手机反而开倒车?为何如今自称旗舰手机还用塑料中框似乎是从5G时代开售,各大手机厂商都开始在自家旗舰机上疯狂堆料,IP68级防尘防水潜望式长焦镜头曲面屏等一套全部都堆上。但随之而来的则是售价上涨,现在各大品牌的旗舰机都已经可以摸到三星GalaxyZFold4驾到,性能爆炸的同时,还迎来了经典设计三星GalaxyZFold4最近在网络上出现了一些曝光图,超自然折叠屏的设计真的惊艳到了我。这一代延续到了上一代的工业设计语言,三星GalaxyZFold4在折叠的状态下身形是非常支付渠道被攻击了有什么好的办法吗?随着移动支付广泛应用,很多人将支付宝或微信支付当做自己的第二个钱包。但是那么多资金放在移动支付平台上,安全吗?最近在一档名为智造将来中,就特地让黑客攻击支付宝账户,通过WIFI和N曝华为MateX3折叠屏手机疑似入网,依旧4G,预搭载麒麟9400G芯片3月30日,星期三,今天,小编就带大家看一款全新的华为手机。这款新的华为4GPL00机型已经获得了工信部的批准。哈S透露,这是华为的MateX3折叠屏手机,预计将搭载麒麟9400G马斯克ampampquot超级富豪税ampampquot要是2008年就存在,特斯拉早就破产了日前美国白宫公布2023年财政预算提案,其中涉及对最富有的美国人征收超级富豪税。白宫方面表示,这项税收将在未来10年减少3600亿美元的斥资,其中大部分税款将来自最富有的700个美美国一女子长期骚扰苹果CEO,法院判她与库克保持200米左右距离来源环球时报环球时报记者刘皓然因长期骚扰苹果公司首席执行官蒂姆库克,美国法院要求一女子未来3年内不得靠近库克。美联社30日报道称,根据法庭文件显示,45岁的朱莉自2020年起频繁向有哪些可以教你做文案的网站推荐?文案,很屌的两个字,有很多学广告的同学把她捧若神明。如果后面再跟个策划两字,绝对逼格满分。也导致很多做运营的人陷进了文案的恐慌中,一提文案,腿肚子直哆嗦。其实,好文案不在纸上,是挂报道称华为等中国公司或面临干预对俄制裁的风险,外交部回应澎湃新闻记者于潇清刘惠4月1日,外交部发言人赵立坚主持例行记者会。有记者提问,有报道称中国通信公司如华为如果继续运输通讯设备给俄罗斯将面临干预对俄制裁的风险,中方对此有何评论?赵立超大户型信号全屋覆盖京东云无线宝AX6600三频路由器全新上市如今,无线网络对于大多数家庭已经成为和水电同等重要的基础资源。随着上网设备越来越多,网络升级提速势在必行,多个城市已经着手推广2000M宽带。而作为网络连接及全屋智能的枢纽,路由器
国内首颗7nm汽车芯发布!对标高通8155,李书福发视频祝贺车东西(公众号chedongxi)作者James编辑晓寒车东西12月11日消息,昨天下午,国内首颗7nm车规级座舱芯片龍鹰一号在武汉发布。龍鹰一号由芯擎科技研发,芯擎科技这家公司由北京提高2022年小客车指标中新能源车指标比例新华社北京12月29日电(记者张骁)北京市小客车指标调控管理办公室29日公告称,将提高2022年北京市小客车指标中新能源指标比例。2022年,北京市小客车指标年度配额10万个。其中华为造车的野心,这次真的藏不住了12月23日,华为召开了冬季旗舰新品发布会。和以往的发布会一样,华为发布了P50Pocket旗舰折叠屏手机华为WATCHD腕部心电血压记录仪华为MateBookXPro华为智能眼镜OPPO备货5700mAh新机,12256G首次下放到2199,值得等说OPPO是今年的国内销量大赢家一点都不为过,因为在华为手机停滞后,其实很多高端机销量到了OPPO那里。可能很多人说明明是小米旗舰更出名,但需要知道的是,目前国产手机销量排名第一的解锁更小更稳更方便的体验!智云云鹤M3带来全新稳定器玩法在影像行业飞速发展的今天,越来越多的人选择用视频来记录生活,也促使产生了各种各样的用于短视频拍摄的设备,并且仍在不断更新迭代。虽然摄影机和相机具有出色的画质和优秀的后期空间,但不选联想七宗罪之三教父的江湖说起柳传志,联想的官方包装中称其为中国商业教父,可事实上,柳传志可并不止步于这个空头衔,如同在联想建立起一手遮天的社会一样,柳传志还建立了一个真正的教派,那就是大名鼎鼎的泰山会。如人工智能科技助力家庭健身来源人民网人民日报海外版本报北京12月10日电(记者聂传清)记者从日前在京举办的小度科技冬季新品发布会上获悉,业界将更加关注健身和健康领域,打造更多人工智能产品,更好服务消费者。百新东方从头再来跨界直播俞敏洪首秀带货农产品超500万元各位亲爱的粉丝朋友好,我是俞敏洪今天我是来卖农产品的。我们初步进入这个领域,如果有选的农品不到位的地方,请网友们多多原谅。12月28日晚上8点,新东方教育科技集团(以下简称新东方)山姆会员店下架新疆产品,中国顾客排队退卡,真不缺一家超市随着美国总统拜登签署最新的涉疆法案,美国国内将全面禁止进口新疆地区商品,这也是美国抹黑新疆的又一个新手段。随后美国多家公司就开始作妖了,英特尔率先要求其供应商不得使用任何新疆产品,防水防摔,新产品AGMX5太牛了AGM正式发布了期待已久的新产品AGMX5。作为首款户外三防5G手机,除了引入了对5G网络的支持外,还选择了全新的升级设计进行进一步维护。表现如何?让我们看看。先来看看外观设计我的如何分辨手机配置的好坏?听懂行人分析这三点,不花冤枉钱现在的智能手机市场可谓是遍地开花,各大厂商层出不穷的产品令我们眼花缭乱,那不同配置的手机我们该如何选择?什么样的配置才能称之为好?别再被厂商忽悠了,认清这三点,你也能成为懂行的人。