有没有办法在javascript中将对象中的值映射到数组的索引?

时间:2015-05-08 18:16:02

标签: javascript jquery arrays performance knockout.js

预先确定解决方案只需要在最新版本的Chrome,Firefox和Safari中使用即可。

-

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

[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
}

4 个答案:

答案 0 :(得分:2)

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

只需在循环中使用

public void addLogButtonOnClickEvent() {
    LogEditFragment addLog = LogEditFragment.get(0l);
    if(mIsLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        addLog.show(getFragmentManager(), "AddLog");
    } else {
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, addLog).addToBackStack(null).commit();
    }
}

如果您的框架是智能的(使用forEach但不是for),它将从您的索引开始(如下所示为500)

http://jsfiddle.net/0axo9Lgp/

DialogFragment

答案 1 :(得分:1)

这不是一个容易解决的问题。我假设你已尝试(或不能尝试)显而易见的事情,例如减少每页的项目数量,并可能使用不同的框架,如React或Mithril。

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

  1. 不要使用每个框架。它比原始数组方法forEach慢或相同,无论哪种方式都比基本for循环慢。
  2. 不要一遍又一遍地遍历数组,寻找数据已更新的每个项目。发送数据更新响应时,请发送更新项目的PKIds数组。然后,做一个循环:
  3. 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数组上的索引来应用直接更新。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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