我有一个像这样排序的二维数组:
testv = sortrows(["zebra" "N" 20; "jimi" "V" 100; "johnny" "V" 200; "pete" "P" 33; "jimi" "N" 20])
现在我基本上想检查是否像
一样"jimi" "N" x
在数组中。如果是,我将增加x,否则我将"jimi" "N" 1
添加到数组中。
执行此操作的懒惰方法只是迭代遍历数组检查所有条目,或编写我自己的二进制搜索,但我保持数组排序以尝试最小化该成本。如果我有办法让searchsorted
为我做这件事,那将是理想的。
如果我可以在searchsorted
上使用"jimi"
,那也没关系 - 我的理解是(如果有效)它会返回"jimi"
出现的范围排序的数组?那没关系,阵列的第二列来自一个足够小的域,我不介意慢慢地循环。
答案 0 :(得分:2)
基础julia中没有很多函数可以处理二维矩阵的行(除了sortrows之外 - 参见apropos("rows")
的输出)。这部分是因为具有不同类型列的矩阵表现不佳,部分原因是因为有一些很好的选择。这里有几个选项可能对你有用。
通过使用元组的向量而不是矩阵,您可以获得更好的性能以及搜索,增长,插入,删除等功能。它还可以确保每个“行”(现在只是一个元素 - 一个元组有适当的类型。
julia> A = [("zebra", "N", 20), ("jimi", "V", 100), ("johnny", "V", 200), ("pete", "P", 33), ("jimi", "N", 20)];
julia> sort!(A) # Sort A in-place
5-element Array{(ASCIIString,ASCIIString,Int64),1}:
("jimi","N",20)
("jimi","V",100)
("johnny","V",200)
("pete","P",33)
("zebra","N",20)
julia> idxs = searchsorted(A, ("matt", "B", 100))
4:3
julia> isempty(idxs) && splice!(A, idxs, [("matt", "B", 100)])
0-element Array{(ASCIIString,ASCIIString,Int64),1}
julia> A
6-element Array{(ASCIIString,ASCIIString,Int64),1}:
("jimi","N",20)
("jimi","V",100)
("johnny","V",200)
("matt","B",100)
("pete","P",33)
("zebra","N",20)
如果您要使用此类数据,则更有吸引力的另一个选项通常是创建自定义类型。设置需要更多的工作,但它允许您创建自己的方法来处理这类数据。
immutable MyData
name::UTF8String
initial::UTF8String
score::Int
end
# We have to tell Julia how to sort these types by defining isless
function Base.isless(a::MyData, b::MyData)
isless((a.name, a.initial, a.score), (b.name, b.initial, b.score))
end
julia> B = [MyData("zebra", "N", 20), MyData("jimi", "V", 100), MyData("johnny", "V", 200), MyData("pete", "P", 33), MyData("jimi", "N", 20)]
julia> sort!(B)
5-element Array{MyData,1}:
MyData("jimi","N",20)
MyData("jimi","V",100)
MyData("johnny","V",200)
MyData("pete","P",33)
MyData("zebra","N",20)
julia> idxs = searchsorted(B, MyData("matt", "B", 100))
julia> isempty(idxs) && splice!(B, idxs, [MyData("matt", "B", 100)])
答案 1 :(得分:1)
一种方法是使用字典。也许这种方法在某种程度上避开了问题的字母,但它很好地适用于提供容易且有效增加的集合的目标。
julia> VERSION
v"0.3.5"
julia> testv = ["zebra" "N" 20; "jimi" "V" 100; "johnny" "V" 200; "pete" "P" 33; "jimi" "N" 20]
创建一个字典,包含从字符串对构造的键和作为总计的值。请注意,顺序与操作数据无关,但可以轻松地对数据进行排序以进行持久化
julia> dv = {[testv[i,1], testv[i,2]] => testv[i,3] for i in 1:size(testv)[1]}
Dict{Any,Any} with 5 entries:
ASCIIString["zebra","N"] => 20
ASCIIString["pete","P"] => 33
ASCIIString["jimi","N"] => 20
ASCIIString["jimi","V"] => 100
ASCIIString["johnny","V"] => 200
julia> for k in sort(collect(keys(dv)), by=(x -> join(x,"")))
println(k[1], " ", k[2], " ", dv[k])
end
jimi N 20
jimi V 100
johnny V 200
pete P 33
zebra N 20
根据需要增加收藏
julia> k = ["mike", "S"]
julia> get!(dv, k, 0)
julia> dv[k] += 1
julia> k = ["matt", "B"]
julia> get!(dv, k, 0)
julia> dv[k] += 1
julia> k = ["jimi","N"]
julia> get!(dv, k, 0)
julia> dv[k] += 1
然后你有
julia> for k in sort(collect(keys(dv)), by=(x -> join(x,"")))
println(k[1], " ", k[2], " ", dv[k])
end
jimi N 21
jimi V 100
johnny V 200
matt B 1
mike S 1
pete P 33
zebra N 20
当然,人们可以添加许多优点,但我认为我已经展示了基本方法。如果您有超出此类的具体问题,我很乐意详细说明。
我应该告诉你如何获得你开始的那种数组:
julia> testv = [[k[1], k[2], dv[k]] for k in sort(collect(keys(dv)), by=(x -> join(x,"")))]
julia> testv = [i[j] for i in tv, j in 1:3]
7x3 Array{Any,2}:
"jimi" "N" 21
"jimi" "V" 100
"johnny" "V" 200
"matt" "B" 1
"mike" "S" 1
"pete" "P" 33
"zebra" "N" 20