golang练手小项目系列(6)-使用map实现set

本文介绍如何在Go中使用map来实现Set数据结构,包括Add、Remove、Cardinality等操作,并探讨如何扩展功能如复制、求差集、交集和并集,同时提出了实现线程安全的Set的思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

go没有提供set数据结构,请用map实现set

要点

需要支持方法:

  • Add 添加元素
  • Remove 删除元素
  • Cardinality 获取 Set 长度
  • Clear 清空 Set
  • Contains 检测元素是否在 Set 中
  • Pop() 随机删除一个元素并返回被删除的元素
  • ToSlice() []interface{} 转换成slice返回

拓展

  • Clone 复制 Set
  • Difference(other Set) Set 返回和另一个Set的差集
  • Equal(other Set) bool 判断和另一个Set是否相等
  • Intersect(other Set) Set 返回和另一个Set的交集
  • SymmetricDifference(other Set) Set 返回不在交集中的元素的集合
  • Union(other Set) Set 返回并集
  • 实现一个线程安全的版本

实现


//set.go

// Package mapset implements a simple and generic set collection.
// Items stored within it are unordered and unique. It supports
// typical set operations: membership testing, intersection, union,
// difference, symmetric difference and cloning.
//
// Package mapset provides two implementations of the Set
// interface. The default implementation is safe for concurrent
// access, but a non-thread-safe implementation is also provided for
// programs that can benefit from the slight speed improvement and
// that can enforce mutual exclusion through other means.
package mapset

// Set is the primary interface provided by the mapset package.  It
// represents an unordered set of data and a large number of
// operations that can be applied to that set.
type Set interface {
   
   
	// Adds an element to the set. Returns whether
	// the item was added.
	Add(i interface{
   
   }) bool

	// Returns the number of elements in the set.
	Cardinality() int

	// Removes all elements from the set, leaving
	// the empty set.
	Clear()

	// Returns a clone of the set using the same
	// implementation, duplicating all keys.
	Clone() Set

	// Returns whether the given items
	// are all in the set.
	Contains(i ...interface{
   
   }) bool

	// Returns the difference between this set
	// and other. The returned set will contain
	// all elements of this set that are not also
	// elements of other.
	//
	// Note that the argument to Difference
	// must be of the same type as the receiver
	// of the method. Otherwise, Difference will
	// panic.
	Difference(other Set) Set

	// Determines if two sets are equal to each
	// other. If they have the same cardinality
	// and contain the same elements, they are
	// considered equal. The order in which
	// the elements were added is irrelevant.
	//
	// Note that the argument to Equal must be
	// of the same type as the receiver of the
	// method. Otherwise, Equal will panic.
	Equal(other Set) bool

	// Returns a new set containing only the elements
	// that exist only in both sets.
	//
	// Note that the argument to Intersect
	// must be of the same type as the receiver
	// of the method. Otherwise, Intersect will
	// panic.
	Intersect(other Set) Set

	// Determines if every element in this set is in
	// the other set but the two sets are not equal.
	//
	// Note that the argument to IsProperSubset
	// must be of the same type as the receiver
	// of the method. Otherwise, IsProperSubset
	// will panic.
	IsProperSubset(other Set) bool

	// Determines if every element in the other set
	// is in this set but the two sets are not
	// equal.
	//
	// Note that the argument to IsSuperset
	// must be of the same type as the receiver
	// of the method. Otherwise, IsSuperset will
	// panic.
	IsProperSuperset(other Set) bool

	// Determines if every element in this set is in
	// the other set.
	//
	// Note that the argument to IsSubset
	// must be of the same type as the receiver
	// of the method. Otherwise, IsSubset will
	// panic.
	IsSubset(other Set) bool

	// Determines if every element in the other set
	// is in this set.
	//
	// Note that the argument to IsSuperset
	// must be of the same type as the receiver
	// of the method. Otherwise, IsSuperset will
	// panic.
	IsSuperset(other Set) bool

	// Iterates over elements and executes the passed func against each element.
	// If passed func returns true, stop iteration at the time.
	Each(func(interface{
   
   }) bool)

	// Returns a channel of elements that you can
	// range over.
	Iter() <-chan interface{
   
   }

	// Returns an Iterator object that you can
	// use to range over the set.
	Iterator() *Iterator

	// Remove a single element from the set.
	Remove(i interface{
   
   })

	// Provides a convenient string representation
	// of the current state of the set.
	String() string

	// Returns a new set with all elements which are
	// in either this set or the other set but not in both.
	//
	// Note that the argument to SymmetricDifference
	// must be of the same type as the receiver
	// of the method. Otherwise, SymmetricDifference
	// will panic.
	SymmetricDifference(other Set) Set

	// Returns a new set with all elements in both sets.
	//
	// Note that the argument to Union must be of the

	// same type as the receiver of the method.
	// Otherwise, IsSuperset will panic.
	Union(other Set) Set

	// Pop removes and returns an arbitrary item from the set.
	Pop() interface{
   
   }

	// Returns all subsets of a given set (Power Set).
	PowerSet() Set

	// Returns the Cartesian Product of two sets.
	CartesianProduct(other Set) Set

	// Returns the members of the set as a slice.
	ToSlice() []interface{
   
   }
}

// NewSet creates and returns a reference to an empty set.  Operations
// on the resulting set are thread-safe.
func NewSet(s ...interface{
   
   }) Set {
   
   
	set := newThreadSafeSet()
	for _, item := range s {
   
   
		set.Add(item)
	}
	return &set
}

// NewSetWith creates and returns a new set with the given elements.
// Operations on the resulting set are thread-safe.
func NewSetWith(elts ...interface{
   
   }) Set {
   
   
	return NewSetFromSlice(elts)
}

// NewSetFromSlice creates and returns a reference to a set from an
// existing slice.  Operations on the resulting set are thread-safe.
func NewSetFromSlice(s []interface{
   
   }) Set {
   
   
	a := NewSet(s...)
	return a
}

// NewThreadUnsafeSet creates and returns a reference to an empty set.
// Operations on the resulting set are not thread-safe.
func NewThreadUnsafeSet() Set {
   
   
	set := newThreadUnsafeSet()
	return &set
}

// NewThreadUnsafeSetFromSlice creates and returns a reference to a
// set from an existing slice.  Operations on the resulting set are
// not thread-safe.
func NewThreadUnsafeSetFromSlice(s []interface{
   
   }) Set {
   
   
	a := NewThreadUnsafeSet()
	for _, item := range s {
   
   
		a.Add(item)
	}
	return a
}



// iterator.go

package mapset

// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
// elements.
type Iterator struct {
   
   
	C    <-chan interface{
   
   }
	stop chan struct{
   
   }
}

// Stop stops the Iterator, no further elements will be received on C, C will be closed.
func (i *Iterator) Stop() {
   
   
	// Allows for Stop() to be called multiple times
	// (close() panics when called on already closed channel)
	defer func() {
   
   
		recover()
	}()

	close(i.stop)

	// Exhaust any remaining elements.
	for range i.C {
   
   
	}
}

// newIterator returns a new Iterator instance together with its item and stop channels.
func newIterator() (*Iterator, chan<- interface{
   
   }, <-chan struct{
   
   }) {
   
   
	itemChan := make(chan interface{
   
   })
	stopChan := make(chan struct
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值