谁能帮助解释这个JavaScript算法[].filter.call()
我的任务是从字符串中按顺序接收唯一元素作为参数。我不明白这个函数uniqueElements如何返回谁能帮助解释这个JavaScript算法[].filter.call(),javascript,arrays,filter,call,Javascript,Arrays,Filter,Call,我的任务是从字符串中按顺序接收唯一元素作为参数。我不明白这个函数uniqueElements如何返回['A','B','C','B'] var word = "AAAABBBBCCBB"; var uniqueElements = function(word) { return [].filter.call(word, (function(elem,index) { return word[index-1] !== elem })); } uniqueEl
['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']
我查阅并阅读了以下资料:
但是没有成功。它对数组对象上的filter方法执行显式的
调用()
,以便它们可以传入字符串。他们只是使用[]
而不是数组
,因为它的语法较短,或者是有人在编写它时试图变得聪明
通常,filter()
方法会影响数组本身的内容。但是,通过call()
-ing它,您可以通过传入另一个数组来更改上下文,或者在本例中是一个字符串(被视为字符数组)。然后为每个元素运行提供的函数,如果函数的返回值为true
var word=“AAAABBBBCCBB”;
var unique=word.split(“”).filter(函数(项、i、ar){
返回ar.indexOf(项目)==i;
}).加入(“”)代码>
相当于
var uniqueElements = function(word) {
return word.split("").filter(function(elem,index) {
return word[index-1] !== elem
});
}
这应该更清楚了:它将单词转换成一个字符数组,然后过滤每个不同于前一个字符的字符。这解释了为什么“B”在结果中出现两次
要获得独特的元素,您可以
var uniqueElements = function(word) {
var res = []
word.split("").forEach(function(val){
if (res.indexOf(val)===-1) res.push(val);
});
return res
}
如果您不了解代码的功能,可以记录操作!即
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()的工作原理
如果您想获取字符串而不是数组,只需添加.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);
为了更好地理解,我将代码分成了更小的部分,并添加了内联注释
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));
这里的[].filter.call
的目的是对字符串应用filter
方法。天真地说,你会首先尝试这样做:
return word.filter(function(elem,index) {
return word[index-1] !== elem;
});
。。。如果word
是一个数组,它将返回其中满足条件word[index-1]!=elem
(是单词[index-1]!==word[index]
)的缩写,即与前面的字符不同的每个字符
但是,filter
方法只存在于从数组
原型继承的对象上,而字符串则不存在这种情况
但是,filter
本身可以处理类似数组的对象,即具有长度
且可能具有数字属性的对象。要调用filter
而不使用真正的Array
对象,可以对该函数使用call
,然后提供上下文(即类似于Array的对象)作为第一个参数。其他参数保持不变。因此,您首先需要知道在哪里可以找到过滤器方法。。。它位于数组中。prototype
,因此您可以这样引用它:
Array.prototype.filter
但是,由于所有数组都可以访问此方法,因此只获取一个空数组并引用其过滤器方法要短一些:
[].filter
return Array.from(word).filter(function(elem,index) {
return word[index-1] !== elem
});
两者中的任何一个都会起作用。现在,您必须对其执行调用方法,并提供要迭代的类似数组的对象:
[].filter.call(words, ...)
其余部分与使用真实数组类似:提供回调函数:
return [].filter.call(word, function(elem,index) {
return word[index-1] !== elem
});
返回值不再是字符串。它就像filter
总是返回一个数组:一个实数组,它是由filter
方法创建的
ES6方式:
在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
});
我将使用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]);
控制台日志(uniques)代码>,用于将字符串转换为字符数组。语法“借用”数组方法,并将其应用于字符串。另请参见。这与在ES6世界中获得编译错误非常相似,可以更简洁易读地写成[…word].filter
,或Array.from(word).filter
。这忽略了他们这样做是为了将filter
应用于字符串的全部要点。您可以传递字符串,因为此引用和筛选器函数将按预期执行拆分(“”)。这是可靠的行为吗?@ganqwerty它不是调用split,而是迭代字符串中的每个字母。字符串是可编辑的,因为它们实际上只是字符数组。