【问题标题】:Removing items from data bound array从数据绑定数组中删除项目
【发布时间】:2010-10-15 18:25:54
【问题描述】:

如何从数据绑定数组中删除项目?我的代码如下。

for(var i = 0; i < listBox.selectedIndices.length; i++) {
  var toRemove = listFiles.selectedIndices[i];
  dataArray.splice(toRemove, 1);
}

提前致谢!

编辑这是我的 swf。添加照片有效,除非您删除项目。 http://www.3rdshooter.com/Content/Flash/PhotoUploader.html

  1. 添加 3 张不同的照片。
  2. 删除第二张照片。
  3. 添加其他照片。
  4. SWF 将第二张照片添加到末尾。

关于为什么会这样做的任何想法?

编辑 2这是我的代码

private function OnSelectFileRefList(e:Event):void
{
    Alert.show('addstart:' + arrayQueue.length);
    for each (var f:FileReference in fileRefList.fileList)
    {
         var lid:ListItemData = new ListItemData();
         lid.fileRef = f;
         arrayQueue[arrayQueue.length]=lid;
    }
    Alert.show('addcomplete:' + arrayQueue.length);
    listFiles.executeBindings();
    Alert.show(ListItemData(arrayQueue[arrayQueue.length-1]).fileRef.name);
    PushStatus('Added ' + fileRefList.fileList.length.toString() + ' photo(s) to queue!');
    fileRefList.fileList.length = 0;
    buttonUpload.enabled = (arrayQueue.length > 0);
}

private function OnButtonRemoveClicked(e:Event):void
{
    for(var i:Number = 0; i < listFiles.selectedIndices.length; i++) {
        var toRemove:Number = listFiles.selectedIndices[i];
        //Alert.show(toRemove.toString());
        arrayQueue.splice(toRemove, 1);
    }
    listFiles.executeBindings();
    Alert.show('removecomplete:' + arrayQueue.length);
    PushStatus('Removed photos from queue.');
    buttonRemove.enabled = (listFiles.selectedItems.length > 0);
    buttonUpload.enabled = (arrayQueue.length > 0);
}

【问题讨论】:

  • 您使用的代码有什么问题? “拼接”不适合你吗?
  • 好像没有。当我向列表框中添加另一个项目时,我得到了前一个项目。

标签: javascript arrays actionscript


【解决方案1】:

知道两件事肯定会有所帮助:

  1. 您的目标是哪个版本的 ActionScript?

  2. 从您的应用程序的行为来看,当用户从要上传的文件列表中删除项目时,该错误不会发生。当用户向列表中添加新项目时,看起来更像是您的逻辑问题。有机会你也可以发布该代码吗?

更新

代替:arrayQueue[arrayQueue.length]=lid

试试:arrayQueue.push(lid)

这将在数组末尾添加一个新项目并将该项目推入该位置。

更新 2

好的,再挖一点。事实证明,每次打开对话框时 fileList 都不会被清除(如果您每次用户选择新文件时都没有创建 FileReferenceList 的新实例)。将每个文件添加到数组后,您需要在 fileList 上调用 splice()。

在您的 AddFile() 方法中尝试类似的操作...

for(var j:int=0; j < fileRefList.fileList.length; j++)
{
     arrayQueue.push(fileRefList.fileList[j]);
     fileRefList.fileList.splice(j, 1);
}

这将使文件列表保持最新,而不是保留以前的选择。

【讨论】:

    【解决方案2】:

    我看到一个问题。从数组中拼接出第一个元素后,选定的索引将不再有效。但这应该只在一次删除多个项目时才会成为问题。

    我认为我们需要查看更多关于您如何处理上传的代码,然后才能弄清楚发生了什么。在我看来,您持有对已删除 FileReference 或其他内容的引用。所描述的问题是在您上传新文件时发生的,而不是在您删除所选文件时发生的。

    【讨论】:

      【解决方案3】:

      你的意思是用listBoxlistFiles 来指代同一个东西吗?

      我在这里有点困难,因为我没有大量的 JavaScript 经验,但我会像在 C、C++ 或 Java 中那样做:将剩余的数组元素复制到它们的新位置。

      假设 listFiles.selectedIndices 已排序(并且其内容是 dataArray 的有效索引),代码将类似于以下内容:

      (警告:后面有未经测试的代码。)

      // Don't bother copying any elements below the first selected element.
      var writeIndex = listFiles.selectedIndices[0];
      var readIndex = listFiles.selectedIndices[0] + 1;
      var selectionIndex = 1;
      while(writeIndex < (dataArray.length - listFiles.selectedIndices.length)) {
        if (selectionIndex < listFiles.selectedIndices.length) {
          // If the read pointer is currently at a selected element,
          // then bump it up until it's past selected range.
          while(selectionIndex < listFiles.selectedIndices.length && 
                readIndex == listFiles.selectedIndices[selectionIndex]) {
            selectionIndex++;
            readIndex++;
          }
        }
        dataArray[writeIndex++] = dataArray[readIndex++];
      }
      
      // Remove the tail of the dataArray
      if (writeIndex < dataArray.length) {
        dataArray.splice(writeIndex, dataArray.length - writeIndex);
      }
      

      编辑 2009/04/04: 您的删除算法仍然存在以下缺陷:当您删除 listFiles.selectedIndices 中的项目时,您会破坏 arrayQueue 中的索引与 @ 中的索引之间的对应关系987654327@.

      要查看此内容,请尝试添加 3 个文件,然后执行“全选”,然后点击删除。它将首先删除列表中的第一个文件(索引 0)。现在曾经列表中的第 2 个和第 3 个文件位于索引 0 和 1。从 listFiles.selectedIndices 获取的下一个值是 1 - 但现在,第 3 个 文件位于索引 1。因此,前一个文件 #3 从数组中拼接出来,使前第二个文件未被删除并位于索引 0。(使用更多文件,您会看到此实现只删除每个数组中的其他文件。)

      这就是为什么我的 JavaScript 代码(上图)使用 readIndexwriteIndex 来复制数组中的条目,跳过要删除的索引上的 readIndex。该算法避免了数组索引之间失去对应关系的问题。 (确实需要仔细编码以防止各种边缘条件。)我尝试了一些 JavaScript 代码类似于我上面写的;它对我有用。

      我怀疑您原始测试用例中的问题(删除第二个文件,然后添加另一个文件)是类似的。由于您只显示了部分代码,我无法判断数组索引和listFiles.selectedIndicesarrayQueuefileRefList.fileList 中的数据是否总是会适当匹配。 (但我怀疑问题在于他们没有。)

      顺便说一句,即使您通过适当调整数组索引值来解决使用splice() 的问题,在一般情况下它仍然是一个 O(N2) 算法。数组复制算法是O(N)。

      【讨论】:

        【解决方案4】:

        我确实需要查看整个类以提供一个明确的答案,但我会编写一个方法来处理从 dataProvider 中删除多个对象并可能分配一个新数组作为列表的 dataProvider 而不是玩弄绑定并在持续时间内使用相同的列表。就像我说的那样,这可能效率低下,并且需要查看问题的上下文,但这就是我会做的 9 除非您在这种情况下非常需要绑定)

        /**
        * Returns a new Array with the selected objects removed 
        */
        private function removeSelected(selectedItems:Array):Array
        {
            var returnArray:Array = []
            for each(var object:Object in this.arrayQueue)
            {
                if( selectedItems.indexOf(object)==-1 )
                    returnArray.push( object )
            }
            return returnArray;
        }
        

        【讨论】:

          【解决方案5】:

          您可能对 blog entry 感兴趣,因为 Java 语言中缺少健壮的迭代器。

          编程语言,你提到的 Javascript,不是问题,我想指出的是健壮迭代器的概念(这篇论文实际上是关于 C++ 作为编程语言)。

          关于为 ET++ C++ 框架提供健壮迭代器的 [研究文档]() 可能仍然有助于解决您的问题。我相信该文档可以为您提供解决问题的必要思路。

          【讨论】:

          • 嗯,这是 JavaScript/EcmaScript/ActionScript 而不是 java。
          • 我不知道为什么,但我不能让降价做我想做的事情:-(
          猜你喜欢
          • 1970-01-01
          • 2011-11-17
          • 2021-10-03
          • 2021-10-19
          • 1970-01-01
          • 2014-09-21
          • 2014-09-21
          • 2020-10-19
          • 1970-01-01
          相关资源
          最近更新 更多