循环遍历数组对象以查找重复项。为什么一个元素返回“未定义”?

时间:2015-11-06 02:05:05

标签: javascript arrays object

我正在尝试实现unique(array)函数,而不使用任何数组库方法(无.push.slice.pop等)。我认为我非常接近解决方案,但我作为测试[2,2,3,3,4,2,2,2,2]传递的数组正在返回[2,undefined,3,undefined,4](在控制台中看起来像[2, ,3, ,4]而不是{{1} }}。知道这里发生了什么吗?我还尝试添加[2,3,4]语句,以便在将if分配给array[i]之前检查returnArray[i]是否未定义,但这不起作用。

array[i]

3 个答案:

答案 0 :(得分:3)

returnArray[returnArray.length] = array[i];代替returnArray[i] = array[i];

答案 1 :(得分:2)

你应该使用索引变量为returnArray赋值。因为returnArray和数组的长度可能不同。

function unique(array){
var index = 0;
var tempObject = {};
var returnArray = [];
for (var i = 0; i < array.length; i++){
  if (!tempObject.hasOwnProperty(array[i])){
    tempObject[array[i]] = true;
    returnArray[index] = array[i];
    index++;
  }
}
return returnArray;
}

答案 2 :(得分:2)

进行锻炼。和乐趣。 我认为使用object[array[i]]hasOwnProperty是作弊的。你说“不使用任何数组方法”,所以你使用对象方法,有点为什么呢?和第二个阵列?在对象键的顶部,完全失去了裸骨的精神,计算字节编码。

你需要像这个难看的难以理解的代币集合。然而非常快,只有5个额外的参考,相比之下优雅。 LOL

function unique(a){
 var i,j,t,b,c
 i=t=j=0
 while((b=a[i])!==c){
     j=0
     while(j<t&&a[j]!==b)j++
     if(j==t)a[t++]=b
     i++
 }
 while(i>=t)a[i--]=c
 a.length=t
 return a
}

在使用length to trim();

之前写入自身和解引用

更新更多详细信息,现在就是答案。

它的作用是遍历读取每个项目的数组,直到它读取一个假定为数组末尾的未定义项目。

当读取每个项目时,它会搜索先前读取的所有项目以检查是否存在匹配项。如果未找到匹配项,则将项目放回到写入位置的数组中,因为它必须是唯一的到目前为止,如果找到一个匹配然后放下该项并循环读取下一个项目。

读写索引。读取索引总是在写入索引之前或者等于写入索引,如果发现某个项目已经存在,那么该项目不会被放回到数组中,并且写入索引不会增加,从而使写入索引落后于读取索引。 / p>

在主循环结束时,writeIndex可能会跟踪读取索引,从而在数组中留下一些不需要的项目。然后我循环遍历readIndex(当前=== array.length)和写入索引之间的所有项目。这是严格不需要的,因为向Array length属性写一个较短的长度具有修剪数组的效果,有效地做同样的事情。我添加了它,因为我想要纯粹的挑战,而不是使用Array方法来修剪数组。 (这是javascript有些事情是不可避免的)

因此,该函数被重写以符合JSLint样式标准。

function unique(array) {
    'use strict';  // required by JSLint standards and really!!... never code JS without it
    // define all variables requierd
    var readIndex,
        searchIndex,
        writeIndex,
        arrayItem,
        undefinedRef;
    // you will notice that I do not indicate undefinedRef, it is undefined after all.
    readIndex = 0; // set the read index to start of the array
    writeIndex = 0; // set the write index to the start of the array
    // check if the readIndex has reached the end of the array
    while (array[readIndex] !== undefinedRef) {
        // get the item at the current readIndex. I could have made the code shorter
        // by not needing the arrayItem and just indexing the array at readIndex
        // in the next loop. But indexing into an array is always slower than
        // using a direct referance. Doing it this way adds a significant performance
        // improvement to the function.
        arrayItem = array[readIndex];
        searchIndex = 0; // set the search index to the start of the array
        // loop untill the search index reaches the write index or a match is found
        while (searchIndex < writeIndex && array[searchIndex] !== arrayItem) {
            searchIndex += 1; // increment the search index
        }
        // the seach index is at the write index then no match has been found
        // the new item must be unique so far so add it to the array
        if (searchIndex === writeIndex) {
            array[writeIndex] = arrayItem; // add the item at the write index
            writeIndex += 1; // increment the write index
        }
        // done for this item increment the readindex and loop
        readIndex += 1;
    }

    // dereferance any unwriten array items at the end of the array.
    // Dont really need this loop as setting the array length does the same thing
    while (readIndex >= writeIndex) {
        array[readIndex] = undefinedRef;
    }
    // remove the undefined items from the array by setting it lenght to the
    // number of items writen back into the array.
    array.length = writeIndex;
    // return the array.
    return array;
}

这就是你如何编写关于函数的大量内容,使它看起来很重要。

<强>更新 另一个不使用任何数组方法。

ES6版本效率不高但非常简单,比上面的版本慢了约20%。也使用更多的内存,但应该只看到上面一个引用计数的两倍。另外,检查重复项的作弊现在由Set.add()处理。虽然为什么比数组索引搜索慢谁知道??

作为单行,因为它看起来不错

var unique=(a)=>{var c,i=0,s=new Set();while((b=a[i])!==c){s.add(b);a[i++]=c}return[...s]}

并扩展了一点(故意删除; {}空格,并使用未定义的c来测试undefined(数组的结尾))我假设数组中没有未定义的值。

这使用Set来剔除重复项。然后传播回到数组

var unique=(a)=>{       // arrow function
    var c,i=0,s=new Set()   // c undefined i=0 starting index and s a new Set
    while((b=a[i])!==c){
        s.add(b);   // add to the set till end of array
        a[i++]=c    // and dereference all array items as we go.
    }
    return [...s]    // convert to array with spread operator and return
}