英文:
Array of arrays in Go or Rust?
问题
我正在将一些旧的 PHP 脚本转换为 Go,以实现更好的性能。然而,旧的 PHP 脚本中充斥着多维数组。以下是代码库中的一部分代码:
while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
$someData[$row['column_a']][$row['column_b']] = $row;
}
// ... 更多查询和其他操作
if (isset($moreData['id']) && isset($anotherData['id']) && $someData[$anotherData['id']][$moreData['id']]) {
echo $someData[$anotherData['id']][$moreData['id']];
}
很糟糕,我知道,但我不能改变逻辑。通过使用 phc 进行编译,我使整个脚本的性能得到了很大的提升,但是转移到一种过程化、静态类型的语言似乎是一个更好的选择。如何在 Go 或 Rust 中高效地复制这些数据结构?在检查索引时需要具有容错能力,脚本中到处都有 isset 来检查数据结构中的标识符是否存在。
英文:
I'm porting some old PHP script to Go in order to achieve better performance. However, the old PHP is full of multidimensional arrays. Some excerpt from the codebase:
while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
$someData[$row['column_a']][$row['column_b']] = $row;
}
// ... more queries and stuff
if (isset($moreData['id']) && isset($anotherData['id']) && $someData[$anotherData['id']][$moreData['id']]) {
echo $someData[$anotherData['id']][$moreData['id']];
}
Awful, i know, but i can't change the logic. I made the whole script perform much better by compiling with phc, but moving to a procedural, statically-typed language seems like a better move. How can i replicate those data structures efficiently with Go or Rust? It needs to be fault-tolerant when it comes to checking indexes, there's a lot of issets all around the script to check if the identifiers exist in the data structures.
答案1
得分: 4
在Go语言中,这可以用map
表示。语法是map[key]value
。例如,要存储一个多维映射[string, string] -> int
,可以使用map[string]map[string]int
。如果你知道索引是整数且密集排列的,那么你应该使用切片。切片更简单,形式为[][]type
。
至于检查键是否存在,可以使用以下语法,其中m是一个映射:
if val, ok := m[key1][key2]; ok {
// 对val进行操作
}
请记住,在向多维映射添加键之前,必须确保内部映射已分配。
if _, ok := m[key]; !ok {
m[key] = make(map[string]int)
}
m[key1][key2] = value
显然,你可能希望将此封装在具有方法或几个简单函数的类型中。
英文:
In Go, this would be represented as a map
. The syntax is map[key]value
. So for example to store a multidimensional map of [string, string] -> int
it would be map[string]map[string]int
. If you know your indices are integers and densely packed, then you'd want to use slices. Those are simpler and look like [][]type
.
As for the checking for a key existing, use this syntax, where m is a map:
if val, ok := m[key1][key2]; ok {
///Do something with val
}
Remember that to add a key to a multidimensional map you'd have to make sure the inner map is allocated before adding to it.
if _, ok := m[key]; !ok {
m[key] = make(map[string]int)
}
m[key1][key2] = value
Obviously you'd want to wrap this up in a type with methods or a few simple functions.
答案2
得分: 3
Rust
PHP数组实际上是关联数组,也被称为映射或字典。Rust在其标准库中使用名称Map。Map
trait提供了各种实现的接口。特别地,这个trait定义了一个contains_key
方法,你可以用它来检查映射是否包含特定的键(而不是写isset($array[$key])
,你写map.contains_key(key)
)。
Map
有两个类型参数:K
是映射的键的类型(即你用作索引的值),V
是映射的值的类型。
如果你的映射需要包含不同类型的键和/或值,你需要使用Any
trait。例如,如果键是字符串,值是不同类型的值,你可以使用HashMap<String, Box<Any>>
(Box
是必需的,因为trait对象是不定大小的;参见这个答案获取更多信息)。查看AnyRefExt
和AnyMutRefExt
的文档,了解如何处理Any
值。
然而,如果可能的类型相对有限,你可能更容易定义自己的trait,并在需要使用这些值的所有地方都使用该trait,而不必在每个地方都显式地进行类型转换(此外,你可以通过添加impl
来添加类型,而无需更改使用值的所有地方)。
英文:
Rust
PHP arrays are actually associative arrays, also known as maps or dictionaries. Rust uses the name Map in its standard library. The Map
trait provides an interface for a variety of implementations. In particular, this trait defines a contains_key
method, which you can use to check if the map contains a particular key (instead of writing isset($array[$key])
, you write map.contains_key(key)
).
Map
has two type parameters: K
is the type of the map's keys (i.e. the values you use as an index) and V
is the type of the map's values.
If you need your map to contain keys and/or values of various types, you'll need to use the Any
trait. For example, if the keys are strings and the values are of various types, you could use HashMap<String, Box<Any>>
(Box
is necessary because trait objects are unsized; see this answer for more information). Check out the documentation for AnyRefExt
and AnyMutRefExt
to see how to work with an Any
value.
However, if the possible types are relatively limited, it might be easier for you to define your own trait and use that trait instead of Any
so that you can implement operations on those types without having to cast explicitly everywhere you need to use the values (plus, you can add types by adding an impl
without having to change all the places that use values).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论