所以我一直在用 Swift 的数组做一些实验。并通过以下代码发现了一些东西:
var shoppingList = ["Chocolate", "Bread", "Cheese", "Apple"]
println(shoppingList)
shoppingList[2..<2] = ["Butter", "Milk"] //Question #1 (Insert after 2nd element)
println(shoppingList)
shoppingList[0..<0] = ["Coffee"]
println(shoppingList)
shoppingList[7..<7] = ["Berry", "Pie"] //Question #2 (Append at the end of array)
println(shoppingList)
给出以下输出:
[Chocolate, Bread, Cheese, Apple]
[Chocolate, Bread, Butter, Milk, Cheese, Apple]
[Coffee, Chocolate, Bread, Butter, Milk, Cheese, Apple]
[Coffee, Chocolate, Bread, Butter, Milk, Cheese, Apple, Berry, Pie]
问题#1:试验 subscript语法,似乎使用 ..<将Insert数组中的一个项目到给定位置(在我的示例中,通过 [2..<2] 在第二个元素之后。与调用数组的 insert(_:atIndex:) 方法相反,这对性能有什么不同吗?或者取决于在这种情况下,可读性 只是使用 insert() 的好处吗?
问题#2:根据此处的 Swift 文档:Collection Type - See Modifying/Accessing Arrays
NOTE
You can’t use subscript syntax to append a new item to the end of an array.
那么我的问题是,为什么我能够使用 [7..<7] 将 2 个元素“Berry”和“Pie”附加到数组的末尾? ?
在撰写本文时,我正在使用 Swift 1.2。
最佳答案
这看起来是个很好的问题,所以我试了一下。
查看使用 7..<7 订阅的示例,半开范围运算符 ..<正在创建 Range看起来像这样的结构:
let range = 7..<7
print(range.startIndex) // 7
print(range.endIndex) // 7
这也许是显而易见的。但是结束索引超出数组边界的范围对数组下标有什么影响?下标函数声明如下所示:
subscript (subRange: Range<Int>) -> ArraySlice<Element>
如果我们调用
let shoppingList = ["Coffee", "Chocolate", "Bread", "Butter", "Milk", "Cheese", "Apple"]
let item = shoppingList[6..<7]
// item: ArraySlice<Int> = "Apple"
我们得到了一片“Apple”,这是您所期望的——我们要了一片 shoppingList包含索引为 6 或更高的元素以及索引低于 7 的元素,因此我们返回一个包含索引 6 处的单个项目的切片。
另请注意此行为:
let item = shoppingList[6...6]
print(range.startIndex) // 6
print(range.endIndex) // 7
endIndex实际上是7 ,但是看看上面的下标,你不会期望有任何问题,你也不会得到任何问题。一种看待这个问题的方法是说 endIndex子范围的索引是要包含在数组切片中的第一个不数组元素的索引。考虑到这一点,我们可以假设下标实现边界检查。
那么这个下标的 getter 的实现是什么样的呢?让我们试试看:
extension Array {
func myRangeSubscript(subRange: Range<Int>) -> ArraySlice<Element> {
if count < subRange.endIndex { fatalError("Out of bounds!") }
var slice = ArraySlice<Element>()
for i in subRange {
slice.append(self[i])
}
return slice
}
}
传入时7..<7 , 因为 x 不存在整数其中 7 >= x < 7 , for 循环不会被输入一次。这就解释了为什么 shoppingList[7..<7]有效,尽管乍一看索引超出范围。
考虑下标赋值可能是什么样子只是进一步的一小步:
subscript(subRange: Range<Int>) -> ArraySlice<Element> {
get {
//...
}
set(newElements) {
// newElements: Array<Element> = []
self.removeRange(subRange)
var elementIndex = 0
for i in subRange {
self.insert(newElements[elementIndex++], atIndex: i)
}
}
}
尽管文档另有说明,但您显然可以“追加”到数组末尾的原因可能是,从语义上讲,您实际上并没有追加 - 您正在替换数组中的一系列元素一个新的元素数组。碰巧的是 n..<n范围,您将用新数组替换一个空 元素数组。从技术上讲,也许不是附加/插入,而是相当古怪的替换!因此,尽管文档在技术上可能是正确的,但实际上他们只是不考虑这种边缘情况。
简而言之,关于性能问题,我不能肯定地说下标实际上是如何实现的。但很明显,至少使用此范围下标执行插入所花费的时间与使用 insert(_:atIndex:) 所花费的时间一样长。或单个索引下标(无论如何很可能调用 insert(_:atIndex:)),因为在准备 ArraySlice 时可能有一些开销待创建,或调用 removeRange(_:) .
出于这个原因,以及它的可读性较差且无法在语义上反射(reflect)您要执行的操作这一事实,我会避免使用此范围下标来插入数组项。坚持使用 insert(_:atIndex:)或相应的下标 - 这就是它们的用途!
关于ios - 在 Swift 中修改数组,(通过下标语法插入和追加),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31872443/
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择