【问题标题】:Is there a way to map a value in an object to the index of an array in javascript?有没有办法将对象中的值映射到javascript中数组的索引?
【发布时间】:2015-07-19 18:04:51
【问题描述】:

预先说明解决方案只需要在最新版本的 Chrome、Firefox 和 Safari 中运行作为奖励。

-

我正在尝试将关联数组用于具有剔除的大型数据集。我的第一次尝试使它成为一个真正的关联数组:

[1: {Object}, 3: {Object},...,n:{Object}]

但淘汰赛对循环播放不满意。于是我尝试了一种作弊方式,希望:

[undefined, {Object}, undefined, {Object},...,{Object}]

数组中的位置是数据库表中的 PK ID。这个数组大约有 3.2k 个项目,大约每 10 秒迭代一次,因此需要速度。我尝试通过拼接来做到这一点,例如

$.each(data, function (index, item) {
    self.myArray.splice(item.PKID, 0, new Object(item));
}

但是 splice 不会创建索引,所以由于我的第一个 PKID 是 1,所以无论如何它仍然插入到 myArray[0]。如果我的第一个 PK 是 500,它仍然会从 0 开始。

我的第二个想法是用var myArray = new Array(maxSize) 初始化数组,但这似乎很重。我希望能够使用某种映射函数来执行此操作,但我不确定如何将键值转换为 javascript 中的索引值。

我的第三个想法是保留两个数组,一个用于轻松查找,另一个用于存储实际值。因此,它几乎结合了前两个解决方案,通过在第一个示例中找到对象的索引并在第二个示例中进行查找。这似乎是有多少人在淘汰赛中管理关联数组,但考虑到数组大小以及它是一个具有不断增长的数据集的实时更新应用程序这一事实,似乎内存密集且在新信息出现时不易管理已添加。

另外,也许我在这里打错了?我们通过敲除将它们放入 DOM 并使用一个名为 isotope 的库进行管理,正如我所提到的,它大约每 10 秒更新一次。这就是为什么我需要快速查找但淘汰赛不想玩我的哈希表尝试。

-- 清晰度编辑: 所以在初始加载时,整个数组都被加载(这是new Array(maxLength) 所在的位置,然后每 10 秒加载一次已更改的任何内容。这就是我要快速更新的信息。

-- 淘汰码:

<!-- ko foreach: {data: myArray(), afterRender: setInitialTileColor } -->
    <div class="tile" data-bind="attr: {id: 'tileID' + $data.PKID()}">
        <div class="content">
        </div>
    </div>
<!-- /ko -->

那么在更新时希望是:

$.each(data.Updated, function (index, item) {
    var obj = myModel.myArray()[item.PKID];
    //do updates here - need to check what kind of change, how long it's been since a change, etc
}

【问题讨论】:

  • 您需要通过PK ID查找物品吗?种类?数字/索引是在前端做任何事情,还是只需要它们从服务器检索数据?
  • 首先,您所展示的不是 javascript 数组的有效语法...发布一些实际的 json。不是 100% 清楚你正在使用什么。另外,您是否控制 API 源输出?
  • 不,它们只是任意的,不会改变。他们有组织 ID,但只有当我们保持相同的系统并且从不切换时,这些才是重要的。这实际上只是为了快速查找,否则在最坏的情况下会变成每 10 秒 9k 循环,平均 4.5k 循环。
  • but knockout was not happy with looping over that. 你是如何尝试用淘汰赛来循环它的?你能应该那个代码吗?也许你的问题就在那里。
  • 这里确实有问题。最坏的情况是你可以使用网络工作者来卸载一些处理,但我猜你有一个设计缺陷

标签: javascript jquery arrays performance knockout.js


【解决方案1】:

这是一个解决方案,如何使用正确的索引填充数组项,因此它不会从第一个开始(我的意思是 0(零))

只在循环中使用

arr[obj.PKID] = obj;

如果你的框架很聪明(使用 forEach 但不用于),它将从你的索引开始(比如下面的 500)

http://jsfiddle.net/0axo9Lgp/

var data = [], new_data = [];

// Generate sample array of objects with index field
for (var i = 500; i < 3700; i++) {
    data.push({
        PKID: i,
        value: '1'
    });
}

data.forEach(function(item) {
    new_data[item.PKID] = item;
});

console.log(new_data);
console.log(new_data.length); // 3700 but real length is 3200 other items are undefined

【讨论】:

  • 在常规 javascript 中工作,但淘汰赛不喜欢那样,我不认为。如果我尝试这样做而不是使用 Array 对象上的方法(推送、弹出、拼接),那么它不会正确更新。我想像这样初始化数组然后将其放入淘汰赛可能是值得的,而不是相反。
  • 所以我尝试了这种方式: var arr = []; $.each(data.customersWithTickets, function (index, item) { arr[PKID] = new Object(item); }); self.Data = ko.observableArray(arr);这遇到了与第一个问题相同的问题,即淘汰模型上的 $data 对象未定义。
  • 能否请您更新您的问题以包含淘汰代码,以便我们可以看到您想要实现的目标并在此基础上帮助您解决问题,因为问题在您的问题标题中,您是太详细了,但是我们应该看到高水平淘汰赛的问题,也许这是您的问题已经存在的简单解决方案。
  • 更新了!我认为我的问题的核心是每次更改我都需要做很多“思考”,因此增加了试图找到它但保持可扩展性的复杂性是很困难的。
  • 我很傻!我的问题是 myArray[0] 是未定义的......因为它从 1 开始。在其余的淘汰赛中添加 &lt;!-- ko if: typeof $data != "undefined"--&gt; 标志会有所帮助,但现在初始加载真的很慢哈哈
【解决方案2】:

这不是一个容易解决的问题。我假设您已经尝试(或无法尝试)明显的东西,例如减少每页的项目数量,并且可能使用 React 或 Mithril 等不同的框架。

我可以提出一些基本的优化建议。

  1. 不要使用框架的 each。它比原生 Array 方法 forEach 慢或相同,无论哪种方式都比基本的 for 循环慢。
  2. 不要一遍又一遍地循环遍历数组以查找数据已更新的每个项目。当您发送数据更新响应时,请发送更新项目的 PKId 数组。然后,做一个循环:

.

var indexes = []
var updated = JSON.parse(response).updated; // example array of updated pkids.
for(var i=0;i<allElements.length;i++){
    if(updated.indexOf(allElements[i].pkid)>-1)
        indexes.push(i);
}

所以,基本上上面假设您有一个简单的对象数组,其中每个对象都有一个名为pkid 的属性来存储其ID。当您收到响应时,您会在此数组上循环一次,将与 pk-id 匹配的所有项目的索引存储在更新后的 pk-id 数组中。

然后您只需遍历indexes 数组并将其元素用作allElements 数组上的索引即可应用直接更新。

【讨论】:

    【解决方案3】:

    如果您的索引是合理范围内的整数,则可以只使用数组。它不必完全填充,您可以使用if 绑定来过滤掉未使用的条目。

    应用更新只是索引数组的问题。

    http://jsfiddle.net/0axo9Lgp/2/

    【讨论】:

      【解决方案4】:

      您可能需要考虑使用publish-subscribe 模式。让每个项目订阅其唯一 ID。当一个项目需要更新时,它将获取事件并自行更新。 This library 可能对此有所帮助。它不依赖于浏览器事件,只依赖于数组,所以它应该相当快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-09-23
        • 2012-07-04
        • 2022-08-19
        • 2021-01-01
        • 1970-01-01
        • 2020-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多