英文:
best way to handle list of integers and to - find, add, and delete
问题
我需要创建一个整数列表,并能够快速添加、删除和查找列表中的项目。虽然我可以创建一个包含它们的字符串和一个处理添加/删除/定位的函数,但如果Go可以为我处理,显然更合理。我看了一下container/list,似乎不完全适合,但也许我错了。
为了快速实现某些东西,我正在使用一个整数数组,但这远非理想的解决方案,我需要找到一个更好的解决方案。这个列表可能会保存多达1,000个值。
请问有人可以建议在Go中处理这个问题的“最佳”方法吗?一个例子胜过千言万语。
英文:
I need to create a list of integers and to be able to quickly add, delete, and find items in that list. While I could create a string containing them and a function to handle the add/delete/locate, it obviously makes more sense if Go can handle it for me. I looked at container/list and it appeared not entirely suitable, but maybe I'm wrong.
To very quickly implement something, I am using an integer array, however that is far from ideal, and I need to find a better solution. The list will probably hold up to 1,000 values.
Can someone please advise the "best" way to handle this in Go? An example is worth 1,000 words.
答案1
得分: 4
没有一个“最好”的方法来回答你的问题,因为你没有说明你想要做什么或者什么样的性能对你来说很重要。数据结构的问题在于,每种结构在不同的情况下表现得更好或更差。一般来说,我会说对于1000个条目,整数切片的性能表现还不错,并且使用起来也不太困难。另外,Nick提出的解决方案也很吸引人,因为它为你提供了对值的O(1)
查找时间(平均值!),而不是在数组中进行O(n)
(未排序)或O(log n)
(已排序)的搜索时间。
Go语言提供了一些操作来实现你提出的[]int
存储方式:
- 获取:
x[i]
- 插入:
x[i] = j
或x = append(x, j)
或使用排序插入 - 删除:
x = append(x[:i], x[i+1:]...)
- 搜索:如果你使用了排序插入,你可以使用
sort.SearchInts
,否则你需要循环并线性搜索。
有关切片的更多操作,请参见这里。
以下示例(playground)为你提供了一个具有O(log n)
搜索时间和O(n)
插入时间的[]int
。
type Ints []int
// 将v插入到ints中,使其保持排序
func (ints *Ints) Append(v int) {
i := sort.SearchInts(*ints, v)
*ints = append((*ints)[:i], append([]int{v}, (*ints)[i:]...)...)
}
// 根据索引删除
func (ints *Ints) Delete(i int) {
*ints = append((*ints)[:i], (*ints)[i+1:]...)
}
func (ints Ints) Search(v int) (int, bool) {
i := sort.SearchInts(ints, v)
return i, i < len(ints) && ints[i] == v
}
data := make(Ints, 0, 1000)
data.Append(100)
index, ok := data.Search(10)
正如你在示例中看到的,Append
会在插入新值时搜索插入位置,根据大小有效地按升序对切片的内容进行排序。这使得可以通过sort.SearchInts
使用二分搜索,将搜索时间从O(n)
降低到O(log n)
。但是,插入时需要进行排序,而排序又是通过搜索插槽来完成的,这在最坏情况下的成本是O(log n)
。因此,插入也是O(log n)
的。
英文:
There is no 'best' way to your question as you don't state what you would like to do or what
sort of performance is important to you. The problem with data structures is, that every structure
performs better or worse depending on the circumstances. Generally I would say that an integer slice
would perform reasonably well for 1000 entries and is not so hard to use. Also the solution Nick
proposed is appealing, as it offers you O(1)
lookup time (average!) for your values instead of
O(n)
(unsorted) or O(log n)
(sorted) search time in an array.
Go offers some operations to implement a []int
store as you proposed:
- get:
x[i]
- insert:
x[i] = j
orx = append(x, j)
or use sorted insertion - delete:
x = append(x[:i], x[i+1:]...)
- search: in case you used sorted insertion, you can use
sort.SearchInts
, otherwise you need to loop and search linearly.
For more operations on slices see here.
The following example (playground) offers you a []int
with O(log n)
time for searching and O(n)
for insertion. Retrieval, deletion and setting
by index is, of course, O(1)
.
type Ints []int
// Insert v so that ints is sorted
func (ints *Ints) Append(v int) {
i := sort.SearchInts(*ints, v)
*ints = append((*ints)[:i], append([]int{v}, (*ints)[i:]...)...)
}
// Delete by index
func (ints *Ints) Delete(i int) {
*ints = append((*ints)[:i], (*ints)[i+1:]...)
}
func (ints Ints) Search(v int) (int, bool) {
i := sort.SearchInts(ints, v)
return i, i < len(ints) && ints[i] == v
}
data := make(Ints, 0, 1000)
data.Append(100)
index,ok := data.Search(10)
As you can see in the example, Append
searches for the place to insert the new value in, depending
on the size, effectively sorting the contents of the slice in ascending order. This makes it possible
to use binary search via sort.SearchInts
, reducing the search time from O(n)
to O(log n)
.
With that comes the cost to sort while inserting, which in turn is done by searching for a slot, which
costs O(log n)
in worst case. Therefore, inserting is O(log n)
as well.
答案2
得分: 3
为了保持简单,我会使用一个map。Map非常快速、高效且内置。
package main
import "fmt"
func main() {
// 创建一个整数集合
xs := make(map[int]bool)
// 向集合中添加一些元素
xs[1] = true
xs[2] = true
xs[3] = true
// 查找元素
if xs[2] {
fmt.Println("找到了2")
} else {
fmt.Println("没有找到2")
}
if xs[8] {
fmt.Println("找到了8")
} else {
fmt.Println("没有找到8")
}
// 删除元素
delete(xs, 2)
// 列出元素
for x := range xs {
fmt.Println("内容", x)
}
}
运行结果为
<pre>
找到了2
没有找到8
内容 3
内容 1
</pre>
这种解决方案可能唯一的缺点是整数没有按照特定顺序排列,这可能对你的应用程序是否重要取决于具体情况。
英文:
In the interest of keeping it simple I would use a map. Maps are very fast, efficient and built in.
package main
import "fmt"
func main() {
// Make our collection of integers
xs := make(map[int]bool)
// Add some things to the collection
xs[1] = true
xs[2] = true
xs[3] = true
// Find them
if xs[2] {
fmt.Println("Found 2")
} else {
fmt.Println("Didn't Find 2")
}
if xs[8] {
fmt.Println("Found 8")
} else {
fmt.Println("Didn't Find 8")
}
// Delete them
delete(xs, 2)
// List them
for x := range xs {
fmt.Println("Contents", x)
}
}
Which produces
<pre>
Found 2
Didn't Find 8
Contents 3
Contents 1
</pre>
Possibly the only disadvantage of this solution is that the integers aren't kept in any particular order, which may or may not be important to your application.
答案3
得分: 0
这实际上更像是一个抽象数据结构的问题。答案取决于你的使用情况。对于一般情况,int的切片会很好(看看append
等),但是如果你希望查找项的效率优于O(n),那么你希望它们是排序的,并且插入到排序的int[]
中的最坏情况是O(n)。
所以问题是你想要优化哪个方面,索引、添加、删除还是搜索?
英文:
This is really more of an abstract data structure question. The answer depends on your use case. A slice of ints would do fine for the general case (look at append
and such), but if you want finding items to be better than O(n) then you'll want them to be sorted, and insertion into a sorted int[]
has a worst case of O(n) iirc.
So the question is which do you want to optimize, index, add, remove, or search?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论