广播范围

Broadcasting ranges

我的数据框中有一个数组数组 - split.(df2.name):

> 392-element Array{Array{SubString{String},1},1}:
 ["chevrolet", "chevelle", "malibu"]
 ["buick", "skylark", "320"]        
 ["plymouth", "satellite"]          
 ["amc", "rebel", "sst"]            
 ["ford", "torino"]                 
 ⋮                                  
 ["ford", "mustang", "gl"]          
 ["vw", "pickup"]                   
 ["dodge", "rampage"]               
 ["ford", "ranger"]                 
 ["chevy", "s-10"]   

我想 select 除了每个数组的第一个元素之外的所有元素并将它们连接在一起,以获得这些汽车的型号名称。

首先,我想做这样的事情:model = join.(split.(df2.name)[2:end], " ") 但不是删除每个数组的第一个元素,而是删除第一辆车(外部数组的第一个元素)。

所以我想通过在范围 model = join.(split.(df2.name).[2:end], " ") 之前放置一个点来将范围 [2:end] 广播到所有元素。但这似乎也不起作用,因为有语法错误:

syntax: missing last argument in "2:" range expression

那么在这种情况下广播范围的朱利安方法是什么?

一般来说,广播索引语法的工作原理是将其转换为 getindex 并广播:

model = join.(getindex.(split.(df2.name), Ref(2:10)), " ")
需要

Ref 才能将范围视为标量;您也可以改用 1 元组。

这是简单的部分。然而,这个技巧与 end 一起使用变得很难看,因为在括号之外它没有任何意义,这就是你得到错误的原因。解决问题的一种方法是将 end 替换为 lastindex,但是您可能应该缓存数组计算:

model = let nameparts = split.(df2.name)
    join.(getindex.(nameparts, Ref(2:lastindex(nameparts))), " ")
end

不过,这失去了广播融合的优势。

在这种特定情况下,您还可以使用 Iterators.rest,因为我们知道 Array 迭代器的工作原理:

join.(Iterators.rest.(split.(df2.name), 2), " ")

但我认为最简单的版本只是一个理解:

model = [join(split(carname)[2:end]) for carname in df2.name]

(除非你对Iterators非常熟悉。那我个人更喜欢前一个。)

在这里使用普通广播似乎有点棘手,因为正如您发现的那样,构建 2:end 范围会显式导致语法错误。我认为这是因为

这样的表达式
a[2:end]

经过特殊解析并降低为类似

的内容
a[2:lastindex(a)]

lastindex 的文档中所述。

然而,您可以使用像 Iterators.drop 这样的迭代器来遍历除第一个元素之外的所有元素,这是一个可以广播的操作:

julia> cars = [["chevrolet", "chevelle", "malibu"],
               ["buick", "skylark", "320"],        
               ["plymouth", "satellite"],          
               ["amc", "rebel", "sst"],            
               ["ford", "torino"]];

julia>  join.(Iterators.drop.(cars, 1), " ")
5-element Array{String,1}:
 "chevelle malibu"
 "skylark 320"
 "satellite"
 "rebel sst"
 "torino"

但我认为在这种情况下,我可能会进行理解,我认为这会更具可读性:

julia> [join(car[2:end], " ") for car in cars]
5-element Array{String,1}:
 "chevelle malibu"
 "skylark 320"
 "satellite"
 "rebel sst"
 "torino"


编辑: 回顾你的全球问题,看起来你首先 split 比你想要的更多,然后努力 join 恢复部分你一开始就不想分开。

因此您可能想利用 splitlimit 关键字参数,这样一开始就不会拆分太多单词:

julia> cars2 = ["chevrolet chevelle malibu",
                "buick skylark 320",
                "plymouth satellite",
                "amc rebel sst",
                "ford torino"];

julia> split.(cars2, " ", limit=2)
5-element Array{Array{SubString{String},1},1}:
 ["chevrolet", "chevelle malibu"]
 ["buick", "skylark 320"]
 ["plymouth", "satellite"]
 ["amc", "rebel sst"]
 ["ford", "torino"]

julia> getindex.(split.(cars2, " ", limit=2), 2)
5-element Array{SubString{String},1}:
 "chevelle malibu"
 "skylark 320"
 "satellite"
 "rebel sst"
 "torino"

最后一个示例还演示了如何通过显式 getindex(a, i) 函数调用广播索引语法,这是语法糖 a[i].

的简化形式