zoukankan      html  css  js  c++  java
  • Go-利用Map实现类似Python的Set数据结构

    该笔记参考《Go并发编程实战》

    • 首先实现一个自定义的HashSet

    利用interface{}作为键,布尔型作为值。

    package main
    
    import (
    	"bytes"
    	"fmt"
    )
    
    type HashSet struct {
    	m map[interface{}]bool
    }
    
    func NewHashSet() {
    	return &HashSet{m: make(map[interface{}]bool)}
    }
    
    func (set *HashSet) Add(e interface{}) bool {
    	if !set.m[e] {
    		set.m[e] = true
    		return true
    	}
    	return false
    }
    
    func (set *HashSet) Remove(e interface{}) {
    	delete(set.m, e)
    }
    
    func (set *HashSet) Clear() {
    	set.m = make(map[interface{}]bool)
    }
    
    func (set *HashSet) Contains(e interface{}) bool {
    	return set.m[e]
    }
    
    func (set *HashSet) Len() int {
    	return len(set.m)
    }
    
    func (set *HashSet) Same(other Set) bool {
    	if other == nil {
    		return false
    	}
    	if set.Len() != other.Len() {
    		return false
    	}
    	for k := range set.m {
    		if !other.Contains(k) {
    			return false
    		}
    	}
    	return true
    }
    
    func (set *HashSet) Elements() []interface{} {
    	initLen := len(set.m)
    	actualLen := 0
    	snapshot := make([]interface{}, initLen)
    
    	for k := range set.m {
    		if actualLen < initLen {
    			snapshot[actualLen] = k
    		} else {
    			snapshot = append(snapshot, k)
    		}
    		actualLen++
    	}
    	if actualLen < initLen {
    		snapshot = snapshot[:actualLen]
    	}
    	return snapshot
    }
    
    func (set *HashSet) String() string {
    	var buf bytes.Buffer
    	buf.WriteString("HastSet{")
    	first := true
    	for k := range set.m {
    		if first {
    			first = false
    		} else {
    			buf.WriteString(" ")
    		}
    		buf.WriteString(fmt.Sprintf("%v", k))
    	}
    	buf.WriteString("}")
    }
    
    • 实现Set的基本特性
    package main
    
    type Set interface {
    	Add(e interface{}) bool
    	Remove(e interface{})
    	Clear()
    	Same(outher Set) bool
    	Elements() []interface{}
    	String() string
    	Len() int
    	Contains(e interface{}) bool
    }
    
    func IsSuperSet(one Set, other Set) bool {
    	if one == nil || other == nil {
    		return false
    	}
    	oneLen := one.Len()
    	otherLen := other.Len()
    	if oneLen > 0 && otherLen == 0 {
    		return true
    	}
    	if oneLen == 0 && oneLen == otherLen {
    		return false
    	}
    
    	for v := range other.Elements() {
    		if !one.Contains(v) {
    			return false
    		}
    	}
    	return true
    }
    
    func Union(one Set, other Set) Set {
    	if one == nil || other == nil {
    		return false
    	}
    	unionedSet := NewSimpleSet()
    	for _, v := range one.Elements() {
    		unionedSet.Add(v)
    	}
    	if other.Len() == 0 {
    		return unionedSet
    	}
    	for v := range one.Elements() {
    		unionedSet.Add(v)
    	}
    	return unionedSet
    }
    
    func Intersect(one Set, other Set) Set {
    	if one == nil || other == nil {
    		return false
    	}
    	intersectedSet := NewSimpleSet()
    	if other.Len() == 0 {
    		return intersectedSet
    	}
    	if one.Len() < other.Len() {
    		for _, v := range one.Elements() {
    			if other.Contains(v) {
    				intersectedSet.Add(v)
    			}
    		}
    	} else {
    
    		for _, v := range other.Elements() {
    			if one.Contains(v) {
    				intersectedSet.Add(v)
    			}
    		}
    	}
    	return intersectedSet
    }
    
    func NewSimpleSet() Set {
    	return NewHashSet()
    }
    func IsSet(value interface{}) bool {
    	if _, ok := value.(Set); ok {
    		return true
    	}
    	return false
    }
    

    至此,一个简单的Set集合就完成了。

  • 相关阅读:
    用友U8 | 【基础设置】添加财务项目分类
    用友U8 | 【出纳管理】通过收支操作出纳收款生单,生成收款单表头信息带不过去
    MySQL经典45题(一)
    用友U8 | 【出纳管理】出纳模块银行日记账提示"已经加过类型为MD的锁"
    用友U8 | 【凭证打印】如何将凭证输出为PDF电子格式
    用友U8 | 【请购单列表】后台数据库导请购单列表
    用友U8 | 【数据权限档案分配】导出客户档案分配表
    用友U8 | 【出纳管理】收支操作,客户收款,出纳收款查询不了相关数据
    鼠标事件中鼠标的坐标是如何定义的
    Visual Studio 中各种文件后缀名是什么意思
  • 原文地址:https://www.cnblogs.com/bvac/p/6272355.html
Copyright © 2011-2022 走看看