我有从string作为参数按顺序接收唯一元素的任务。我不明白这个函数 uniqueElements 如何返回['A','B','C','B']
。
var word = "AAAABBBBCCBB";
var uniqueElements = function(word) {
return [].filter.call(word, (function(elem,index) {
return word[index-1] !== elem
}));
}
uniqueElements(word);
//it should return ['A','B','C','B']
我检查并阅读了以下来源:
MDN Mozilla和JS Blog但没有成功。
答案 0 :(得分:2)
此处[].filter.call
的目的是在字符串上应用filter
方法。天真地你会先尝试这样做:
return word.filter(function(elem,index) {
return word[index-1] !== elem;
});
... - 如果word
是一个数组 - 会返回满足条件word[index-1] !== elem
的字符(word[index-1] !== word[index]
的缩写),即每个字符这与之前的角色不同。
但是,filter
方法仅存在于从Array
原型继承的对象上,而不是字符串的情况。
但是,filter
本身可以处理类似数组的对象,即具有length
且可能具有数字属性的对象。要在没有真正filter
对象的情况下调用Array
,可以在该函数上使用call
,然后提供上下文(即类似数组的对象)作为第一个参数。其他论点保持不变。因此,您首先需要知道在哪里找到filter
方法...它位于Array.prototype
上,因此您可以像这样引用它:
Array.prototype.filter
但是由于所有数组都可以访问此方法,因此只需要一个空数组,并引用其filter
方法:
[].filter
两者中的任何一个都可以。现在你必须对它执行call
方法,并提供你想迭代的类似数组的对象:
[].filter.call(words, ...)
其余的就像你使用真正的数组:你提供回调函数:
return [].filter.call(word, function(elem,index) {
return word[index-1] !== elem
});
返回值不再是字符串。它就像 - filter
总是返回 - 一个数组:一个真正的 - 它是由filter
方法创建的。
在ES6中,您可以用更易读的方式编写它,因为现在有Array.from
方法,它可以将类似数组的对象转换为真正的数组。然后您可以继续使用filter
方法:
return Array.from(word).filter(function(elem,index) {
return word[index-1] !== elem
});
传播运营商是ES6提供的另一种选择:
return [...word].filter(function(elem,index) {
return word[index-1] !== elem
});
答案 1 :(得分:1)
它对数组对象上的filter方法执行显式call()
,以便它们可以传入一个字符串。他们只是使用[]
而不是Array
,因为它的语法较短或有人试图在写作时变得聪明。
通常,filter()
方法会影响数组自己的内容。但是,通过call()
,你可以通过传入另一个数组来改变上下文,或者在这种情况下,传入一个字符串(被视为一个字符数组)。然后它为每个元素运行提供的函数,如果函数的返回值为true
,则保留元素。
答案 2 :(得分:1)
var uniqueElements = function(word) {
return [].filter.call(word, (function(elem,index) {
return word[index-1] !== elem
}));
}
相当于
var uniqueElements = function(word) {
return word.split("").filter(function(elem,index) {
return word[index-1] !== elem
});
}
应该已经更清楚了:它将word转换为char数组,然后过滤掉与前一个不同的每个char。这解释了为什么" B"在结果中出现两次。
要获得独特元素,您可以
var uniqueElements = function(word) {
var res = []
word.split("").forEach(function(val){
if (res.indexOf(val)===-1) res.push(val);
});
return res
}
答案 3 :(得分:0)
如果您不了解代码的作用,您可以记录操作! IE
var word = "AAAABBBBCCBB";
function uniqueElements(word){
return [].filter.call(word,(
function(elem,index) {
console.log("Index : "+index+" | Elem : " +elem+" | CompareTo "+word[index-1]);
return word[index-1] !== elem;
}
));
}
uniqueElements(word);
您将获得以下输入:
Index : 0 | Elem : A | CompareTo undefined
Index : 1 | Elem : A | CompareTo A
Index : 2 | Elem : A | CompareTo A
Index : 3 | Elem : A | CompareTo A
Index : 4 | Elem : B | CompareTo A
Index : 5 | Elem : B | CompareTo B
Index : 6 | Elem : B | CompareTo B
Index : 7 | Elem : B | CompareTo B
Index : 8 | Elem : C | CompareTo B
Index : 9 | Elem : C | CompareTo C
Index : 10 | Elem : B | CompareTo C
Index : 11 | Elem : B | CompareTo B
使用它,您可以检查每个不等于之前的元素是否都发送到您的数组。
很少有答案/评论已经指出[] .filter.call()如何运作。
如果您想获取String而不是数组,只需添加.join("")
IE
var word = "AAAABBBBCCBB";
function uniqueElements(word){
return [].filter.call(word,(
function(elem,index) {
console.log("Index : "+index+" | Elem : " +elem+" | CompareTo "+word[index-1]);
return word[index-1] !== elem;
}
)).join("");
}
uniqueElements(word);
答案 4 :(得分:0)
我已将代码拆分为带有内联注释的较小部分,以便更好地理解。
var word = "AAAABBBBCCBB";
var uniqueElements = function(word){
// this is the filter function
// this function will get each element of the string with its index
var filterFunction = function(elem, index) {
// the elements who pass the following condition are kept
// the condition -
// if the character at the previous index (index-1) is not equal to the
// current element, then keep the element
return word[index-1] !== elem;
}
// the below is equivalent to Array.prototype.filter.call(context, filterFunction)
return [].filter.call(word, filterFunction);
}
console.log(uniqueElements(word));
答案 5 :(得分:0)
我会按照以下方式使用Array.prototype.reduce()
做O(n)时间;
var str = "AAAABBBBCCBB",
uniques = Array.prototype.reduce.call(str, (p,c,i) => i-1 ? p[p.length-1] !== c ? (p.push(c),p)
: p
: [c]);
console.log(uniques);
答案 6 :(得分:-1)
var word = "AAAABBBBCCBB";
var unique = word.split('').filter(function(item, i, ar) {
return ar.indexOf(item) === i;
}).join('');