【问题标题】:Deep understanding: What is the underlying logic behind the way array indexes work?深入理解:数组索引工作方式背后的底层逻辑是什么?
【发布时间】:2015-04-29 11:27:09
【问题描述】:

我提出这个问题的动机

对我来说,编程的快感在于对给定语言背后的逻辑的深刻理解使您能够使用该逻辑“解决问题”。因此,当我偶然发现似乎错过了这种逻辑的东西时,我会感到困扰。

索引的工作原理

这是我学到的关于使用数组索引的知识:

var fruit = ["Apple", "Orange", "Kiwi"]

fruit.length = 3 // returns the length of the fruit array

var rotten = fruit[2] //assigns the value "Kiwi" to the variable "rotten"

fruit[2] = "Melon" //changes the 3rd object in the array fruit from "Kiwi" to "Melon"
fruit[fruit.length] = "Melon" //adds a new object to the array fruit after "Kiwi"

逻辑有什么困扰我

所以我刚刚使用.length获取我的水果数组长度为3的信息。接下来我想使用var rotten = fruit[] 访问第三个对象。我的逻辑告诉我应该使用var rotten = fruit[3] 来执行此操作。但这会返回 undefined,因为对象的索引为 0、1、2。

同样,我的直接想法是使用以下代码将对象添加到数组中:fruit[fruit.length + 1] = "Melon" 因为我知道.length 方法返回数组中的“最后一个对象的编号”。当然实际情况并非如此,因为当考虑索引为 0、1、2 时,这实际上是 2。

我的问题

在不使用 1、2、3 而不是 0、1、2 来索引数组的背后是否有更深层次的逻辑,从而使 - 在我看来 - 更直观地理解和使用 Javascript 或者这只是你应该做的事情了解我的内心并接受而不寻找任何更深层次的理由?

【问题讨论】:

  • 谢谢大家。我的目的不是引发一场辩论——只是认为实际上可能存在潜在的逻辑。似乎从答案中可以看出,即使您可能在某种程度上可以为这两种索引提出论据,但似乎没有 - 这是另一个时间和地点的辩论。

标签: javascript arrays indexing string-length


【解决方案1】:

在 Fortran 系列语言中,数组的索引从 1 开始,正如您所建议的,因为这是标准的数学实践。在 Algol-60/PASCAL 系列语言中,程序员选择起始索引——它可以是 0、1 或其他任何值。在 BCPL 和 C 语言家族以及大多数现代语言(明显排除 Julia)中,数组索引从 0 开始。

多年来,发现使用单一约定很方便——PASCAL 风格的索引在组合不同程序员编写的代码时会混淆,最好选择一个起始索引并坚持下去。

0 和 1 之间的实际选择是相当随意的,但许多 wise people 同意从 0 开始使许多操作更简单,更不容易出错。例如比较以下两种数组交错的实现,从 0 开始:

if(i % 2 == 0)
    a[i / 2] = 42;
else
    b[(i - 1) / 2] = 42;

和基于 1 的:

if(i % 2 == 1)
    a[(i + 1) / 2] = 42;
else
    b[i / 2] = 42;

【讨论】:

  • 嗯,您的示例似乎完全相同 - 您使用相同数量的表达式和常量。我什至认为人们在直觉上处理+- 更好。 Dijkstra 注意到1 <= i < N + 10 <= i < N 更“丑陋”是一个稻草人——大多数使用pascal 的人都使用1 <= i <= N,这比IMO 更好——只是一个简单的[1..N],对于PASCAL 来说是完全合理的,它与像这样的概念一起工作套。
  • 当然。正如我所说,重要的一点是选择一个约定并让每个人都遵守它——而且业界似乎已经对基于 0 的约定进行了标准化,所以我建议效仿。我个人觉得基于 1 的约定令人困惑,但也许这只是因为我已经习惯了基于 0 的约定。
  • 在类 C 的世界中,是的。 C 与当时的硬件保持密切联系——这就是我们获得从 0 开始的索引的方式(pointer + size * i 是一个简单的偏移量,大多数 CPU 都有执行该操作的指令,而pointer + size * (i-1) 需要一个额外的步骤;当然,编译器可以将基于 1 的值更改为基于 0 的值,但 C 编译器非常简单;有趣的是,较旧的 PASCAL 编译器虽然是单通道的,但对此没有问题)和以空字符结尾的字符串(它们具有直接某些 CPU 上的硬件支持)等。其他语言有不同的约定。
猜你喜欢
  • 2021-03-30
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多