大于/小于的 switch 语句

2024-03-29

所以我想使用这样的 switch 语句:

switch (scrollLeft) {
  case (<1000):
   //do stuff
   break;
  case (>1000 && <2000):
   //do stuff
   break;
}

现在我知道这些陈述中的任何一个(<1000) or (>1000 && <2000)不起作用(显然出于不同的原因)。我要问的是做到这一点的最有效的方法。我讨厌使用 30if语句,所以我宁愿使用 switch 语法。有什么我可以做的吗?


查看其他答案中的解决方案,我发现根据过去的经验,我发现一些对性能不利的事情。

我已经在不同的浏览器中测试了多种解决方案,下面是我的结果(ymmv),根据每个浏览器中最快的操作进行标准化。

这是 2021 年 5 月 5 日的结果

Test Chrome Firefox Opera Edge Brave Node
1.0 time 15 ms 14 ms 17 ms 17 ms 16 ms 14 ms
if-immediate 1.00 1.00 1.00 1.00 1.00 1.00
if-indirect 2.20 1.21 2.06 2.18 2.19 1.93
switch-immediate 2.07 1.43 1.71 1.71 2.19 1.93
switch-range 3.60 2.00 2.47 2.65 2.88 2.86
switch-range2 2.07 1.36 1.82 1.71 1.94 1.79
switch-indirect-array 2.93 1.57 2.53 2.47 2.75 2.50
array-linear-switch 2.73 3.29 2.12 2.12 2.38 2.50
array-binary-switch 5.80 6.07 5.24 5.24 5.44 5.37

2021 年的测试在 Windows 10 64 位、以下版本上进行:铬90.0.4430.212, 火狐浏览器89.0b13, 歌剧 76.0.4017.123, 边缘90.0.818.62, 勇敢者 1.24.85, and 节点16.1.0(在 WSL 下运行)

苹果不更新了Windows 版 Safari,所以仍然是5.1.7。我在这次测试中将其更改为Brave。

以下是 2012 年 9 月 4 日的结果,用于历史比较:

Test Chrome Firefox Opera MSIE Safari Node
1.0 time 37 ms 73 ms 68 ms 184 ms 73 ms 21 ms
if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
if-indirect 1.2 1.8 3.3 3.8 2.6 1.0
switch-immediate 2.0 1.1 2.0 1.0 2.8 1.3
switch-range 38.1 10.6 2.6 7.3 20.9 10.4
switch-range2 31.9 8.3 2.0 4.5 9.5 6.9
switch-indirect-array 35.2 9.6 4.2 5.5 10.7 8.6
array-linear-switch 3.6 4.1 4.5 10.0 4.7 2.7
array-binary-switch 7.8 6.7 9.5 16.0 15.0 4.9

2012年的测试是在Windows 7 32位以下版本上进行的:铬21.0.1180.89m, 火狐15.0, 歌剧 12.02, MSIE 9.0.8112, Safari 5.1.7. Node在 Linux 64 位机器上运行,因为 Windows 的 Node 上的计时器分辨率是 10 毫秒,而不是 1 毫秒。

if-立即

这是所有测试环境中最快的方法,除了......drumroll微星! (惊讶,惊讶)。

这是推荐的实施方式。

if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else

if-间接

这是一个变体switch-indirect-array但与if-语句代替,并且在所有测试的引擎中速度更快。

2021 年,它比最快的测试慢了 20-120%(2012 年:0-280%)。 Chrome 在 2021 年 (2.20) 花费的时间比 2012 年 (1.2) 更长

values=[
   1000,  2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else

立即切换

当您可以进行计算以获得索引时,这很有效。

2021 年,速度比 2012 年慢 40-120%(2012 年:0-180%)if-immediate,除了 MSIE,它实际上是最快的。

switch (Math.floor(val/1000)) {
  case 0: /* do something */ break;
  case 1: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

开关范围

它很慢,因为引擎必须为每种情况比较两次值。

2021 年,它比最快的测试慢了 1-2.6 倍(2012 年:1.6-38)倍。 Chrome 的改进最大,从 38 到 3.6,但仍然是经过测试的最慢的引擎。

switch (true) {
  case (0 <= val &&  val < 1000): /* do something */ break;
  case (1000 <= val &&  val < 2000): /* do something */ break;
  ...
  case (29000 <= val &&  val < 30000): /* do something */ break;
}

开关范围2

这是一个变体switch-range但每个案例仅进行一次比较,因此速度更快。 case 语句的顺序很重要,因为引擎将按源代码顺序测试每个 caseECMAScript 2020 13.12.9 https://262.ecma-international.org/11.0/#sec-runtime-semantics-caseblockevaluation

2021 年,它比最快的测试慢了 36-107%,但 2012 年却慢了 1-31 倍。在这次测试中表现最差的仍然是 Chrome,但它已经从 32 倍提高到了 2 倍。

switch (true) {
  case (val < 1000): /* do something */ break;
  case (val < 2000): /* do something */ break;
  ...
  case (val < 30000): /* do something */ break;
}

开关间接数组

在此变体中,范围存储在数组中。

2021 年,它比最快的测试慢了 57-193%(2012 年:3-35 倍)。 所有测试引擎的性能都有所提高,虽然 Chrome 仍然是最慢的,但它已从 35 提高到 2.93。

values=[1000,  2000 ... 29000, 30000];

switch(true) {
  case (val < values[0]): /* do something */ break;
  case (val < values[1]): /* do something */ break;
  ...
  case (val < values[29]): /* do something */ break;
}

数组线性搜索

在此变体中,范围存储在数组中。

2021 年,它比最快的测试慢了 57-193%(2012 年:3-35 倍)。 所有测试引擎的性能都有所提高,虽然 Chrome 仍然是最慢的,但它已从 35 提高到 2.93。

values=[1000,  2000 ... 29000, 30000];

for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
  if (val < values[sidx]) break;
}

switch (sidx) {
  case 0: /* do something */ break;
  case 1: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

数组二进制开关

这是一个变体array-linear-switch但使用二分搜索。 不幸的是它比线性搜索慢。我不知道这是我的实现还是线性搜索更优化。也可能是密钥空间太小。

2021 年,这一速度慢了 4-5 倍(2012 年:4-16)倍。不使用.

values=[0, 1000,  2000 ... 29000, 30000];

while(range) {
  range = Math.floor( (smax - smin) / 2 );
  sidx = smin + range;
  if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}

switch (sidx) {
  case 0: /* do something */ break;
  ...
  case 29: /* do something */ break;
}

结论

如果性能很重要,请使用if- 陈述或switch,具有立即值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大于/小于的 switch 语句 的相关文章

  • 如何更改Android中开关的文本颜色

    我正在创建一个使用 Android 4 0 的应用程序 我想知道是否可以更改开关中文本的文本颜色 我尝试过设置文本颜色 但不起作用 有任何想法吗 提前致谢 你必须使用android switchTextAppearance属性 例如 and
  • Ace Editor 获取当前选定的行号和文本

    我目前正在使用 Ace Editor 但我在文档中找不到与检索当前所选行号及其文本相关的任何内容 有任何想法吗 首先 定义 选定行 ace 中的选择可以跨多行设置 如果您的意思是 未设置选择 当前行是光标闪烁的行 var currline
  • GWT 与 ScriptSharp 的优缺点 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 无法通过 phantomjs 网络服务器传送图像文件

    我正在尝试让 phantomjs 网络服务器为我工作 我想提供 2 个文件 html 文件和 png 图像文件 html 文件服务良好并在浏览器中正确呈现 但 png 文件不是 这是服务器的代码 var fs require fs func
  • 使用 CORS 进行 React 中的 Fetch 时出现问题

    我对 CORS 完全陌生 并且遇到以下问题 我正在使用 create react app 端口 3000 调用 spring boot 端口 8080 中创建的一些 REST 服务 我将 JWT 身份验证添加到我的 REST API 中 因
  • Angular:将数据从工厂 ajax 调用传递回我的控制器

    我一直在使用 Angular 并且已经从使用本地数据 似乎工作正常 转向尝试通过工厂中的 ajax 调用来填充我的视图 这是代码 div h2 Get data using a Factory h2 div div div
  • 在 Javascript 中获取类的所有实例

    我以为这个问题已经有了答案 但我似乎找不到答案 如何在 Javascript 中的此类的所有实例上运行特定的类方法 这必须在我不知道实例名称的情况下完成 我想我可以在类中使用某种静态变量来存储所有实例 但这在 JS 中似乎不存在 那么如何在
  • 分层边缘捆绑:添加父组标签

    我对 HTML 和 JavaScript 还很陌生 我面临着著名的分层边缘捆绑可用here https bl ocks org mbostock 7607999 由 D3 js 库生成 My goal is to add a semi ci
  • 在我自己的文件夹结构中的 Sequelize 中的迁移

    我是新来的Sequelize我当前的项目要求我将它与迁移一起使用 我熟悉迁移的内容和方式 我来自Django背景 每个子应用程序在同一文件夹中都有模态 视图 api url 和迁移 我喜欢这个结构 并希望在我的 Nodejs 应用程序中保持
  • 将颜色渐变应用于网格上的材质 - Three.js

    我有一个 STL 文件加载到我的场景中 并将单一颜色应用于 phong 材质 我想要一种方法 将两种颜色应用于该网格物体的材质 并在 Z 轴上应用渐变效果 如下例所示 渐变花瓶 https i stack imgur com Ty9gq j
  • 动态创建多个上传文件

    我想知道是否有人知道动态创建上传表单的最佳方法 这就是我想要实现的目标 下面显示的代码允许一次上传 我想要一个按钮 按下该按钮后 应添加另一种形式用于文件上传 因此 如果我想上传 假设有 7 个文件 我想按按钮 7 次来创建这些上传表单 每
  • IE 中“对象不支持属性或方法‘查找’”

  • 通过 AJAX 加载 Google Maps API,控制台错误

    我正在使用 jquery javascript ajax 和 php 构建一个完全动态的网站 当我单击导航链接时 浏览器会使用 ajax 打开该页面 所以基本上所有页面都加载在同一个index php 中 如果我转到 位置 选项卡 其中有谷
  • Knockout JS 与 Ratchet 和 Push.js 配合得很好,直到我添加数据转换

    我正在使用 Ratchet js push js 库为移动 Web 应用程序创建 UI 在这个库中 链接是通过将要加载的文件 推送 到 content DOM 元素中而不是加载整个页面来处理的 但是 push js 在加载页面时不会加载它找
  • 在 AngularJS 中使用 iFrame

    Using Angular 1 2 我正在尝试找出一种 有角度 的方式来加载 iFrame 但我在任何地方都找不到任何教程 任何真正的讨论 基本上 我有一个显示链接列表的搜索页面 单击链接应调用控制器中的一个函数 该函数将数据 可能通过 h
  • FB.logout() - 无访问令牌 - “以不同用户身份登录”

    这个问题与这个问题相关 在没有访问令牌的情况下调用 FB logout https stackoverflow com questions 8430474 fb logout called without an access token 1
  • IFrame Resizer 未调整大小

    我正在这个页面上工作 http factor1hosting com dnaz wordpress certifications http factor1hosting com dnaz wordpress certifications 我
  • 使用 v-bind Vue.js 的多个变量

    我试图在以下代码中传递多个变量 div div 但我收到以下错误 Vue warn 无法生成渲染函数 SyntaxError 意外的标记 在 我尝试更换 with a 但我得到 Vue warn 无法生成渲染函数 SyntaxError I
  • Google Closure 事件委托 a'la jQuery live/on

    我需要将事件委托给新创建的元素 我需要将处理程序附加到它们的创建事件 类似于 onCreate 我不想在创建后通过寻址将事件绑定到元素 jQuery element click function 我更喜欢类似的东西 on document
  • 返回深度嵌套数组中对象的索引的函数

    我可能需要编写一个函数 仅输出数组内对象的索引 显然 使用 inArray 在下面的示例中返回这个索引就可以了 array one two three inArray one array 0 对于更复杂的数组 如何找到嵌套对象的索引 arr

随机推荐

  • 电子表格函数中返回数组

    下面的代码返回一个数组 我想在电子表格中使用它作为 Excel 公式来返回数组 但是 当我这样做时 它只将第一个值返回到单元格 无论如何 是否可以返回与数组大小相同的范围内的数组 Function LoadNumbers Low As Lo
  • ./node_modules/bootstrap-loader/no-op.js 中出现错误

    我在我的应用程序中使用 Webpack 其中我将入口点创建为 index ts 并且我尝试使用 sass css bootstrap typescript 作为我的项目 webpack 中的资源来运行它 但我遇到了这些错误 bootstra
  • 如何从jetty-maven-plugin获取端口号?

    jetty maven 插件 7 x http wiki eclipse org Jetty Feature Jetty Maven Plugin 当用于集成测试时 在运行时动态查找可用端口 如何保存找到的端口号并在 Java 集成测试中使
  • 如何将sklearn决策树规则提取为pandas布尔条件?

    有这么多帖子像这样 https stackoverflow com questions 20224526 how to extract the decision rules from scikit learn decision tree关于
  • 如何处理与 hgsubversion 的合并?

    我正在尝试为使用 Subversion 的项目做出贡献 我使用 Mercurial 及其 hgsubversion 扩展来克隆存储库 我的工作发生在功能分支上 如何使功能分支与默认分支 hgspoke 又名主干 svnspoke 上发生的事
  • Spring Boot RestController,错误状态响应主体,错误消息为空

    在我的 Spring Boot RestController 上 我想通过抛出自定义异常来将自定义错误消息传递到响应正文 我正在遵循指南https dzone com articles spring rest service excepti
  • 将 log4net 与 WebApi 结合使用 - 在整个实例中保持相同的相关 ID

    我有一个 LoggingHandler 类 用作消息处理程序来记录 使用 log4net 请求和对我的 WebApi 的响应 public class LoggingMessageHandler DelegatingHandler publ
  • 在 Google 日历中设置事件颜色

    使用谷歌日历API http code google com apis calendar 我可以成功add http code google com apis calendar data 2 0 developers guide dotne
  • Dealloc 被调用两次?

    解决 感谢孤独枪手 这个问题是由于在释放许多代表之前没有将其设置为零而造成的 这是一个奇怪的 我熟悉基本的内存管理 但我认为我所看到的有些不寻常 这是一些背景 我有一个 NavigationController 来处理以下 ViewCont
  • “Binding”类型的 DependencyProperty 未更新

    我在创建 Binding 类型的 DependencyProperty 时遇到问题 其他类型工作正常 如果我使用绑定填充它们 它们就会成功解析 在我的场景中 我想获取原始绑定 以便我可以使用它来绑定到子对象的属性 这与 DataGrid 处
  • 相对于视图的CGPoint

    考虑一个屏幕点 CGPoint 和一个视图 UIView 它位于视图层次结构内部的某个位置 它可以是其他视图的子视图 如何将点转换为相对于视图坐标的点 首先 将该点从屏幕坐标转换为主窗口的坐标 UIWindow mainWindow UIA
  • 分配新值后将 ObservableCollection 绑定到 DataGrid

    这似乎是一个简单的问题 但我无法让它发挥作用 我有一个具有以下属性的用户控件 public ObservableCollection
  • 仅当 IP 地址获得批准时才允许用户访问页面

    如何制作一个 HTML 和 CSS PHP JavaScript 文档 只允许页面上的某些 IP 地址 我不是问 how 使用 PHP 查找 IP 地址 但如何允许基于 IP 地址访问页面 把它放在你的 php 文件的顶部并更新allowe
  • 用于创建断开连接的数据库应用程序的最佳基于 .NET3.5 的策略

    我的要求是 相对较小的数据库 25 30 个表 每个表有 4 5k 行 4 5 个用户在其笔记本电脑上拥有自己的本地数据库副本 在需要时或一天结束时进行同步 免费解决方案 正如我为 NFP 组织进行的设置一样 过去几天我一直在研究各种选择
  • 如何调试肉桂小程序?

    我想写一个肉桂小程序 这些都是基于 JavaScript 的 我希望编写的代码更改服务 打开和关闭它们 类似于WebDeveloper菜单小程序 https bitbucket org infiniteshroom cinnamon web
  • 仅保留 git 中文件子集的提交

    我想实现以下目标 保留我选择的文件的所有更改历史记录 或提交 有些文件被重命名 有些文件也从其他目录移动 我想删除与我从 git 日志中选择的文件无关的所有提交 我尝试了不同的方法 例如this https medium com ayush
  • 如何通过http打开远程sqlite数据库?

    是否可以通过 http 打开 sqlite 文件 我只需要读取数据库 并希望我可以做类似的事情 var dbFile File new File http 10 1 1 50 project db sqlite sqlConnection
  • Angular View 绑定未使用简单布尔值更新

    再见 这可能是一个菜鸟问题 但我无法让它发挥作用 我有一个简单的服务 可以切换布尔值 如果布尔值为 true 则活动类应该出现在我的 div 上 如果为 false 则没有类 就这么简单 但是布尔值已更新 但我的视图没有对此做出反应 我是否
  • if match 语句中的 #N/A 返回 FALSE

    如果出现匹配错误 我会尝试显示 FALSE 值 现在 我还无法弄清楚 我对谷歌电子表格中的公式如何工作仍然很陌生 IF MATCH A16 W46 W52 0 TRUE FALSE 如果该值存在 则当前有效 我努力了 IF ISNA MAT
  • 大于/小于的 switch 语句

    所以我想使用这样的 switch 语句 switch scrollLeft case lt 1000 do stuff break case gt 1000 lt 2000 do stuff break 现在我知道这些陈述中的任何一个 lt