当我看到我找到的unique()
函数时
它将一个数组作为参数并返回一个包含该数组的唯一元素的新数组(这意味着没有重复的项)。但是我无法理解这个功能的逻辑。有人可以向我解释一下吗?
这是功能:
function unique ( array ) {
return array.filter(function(a){
return !this[a] ? this[a] = true : false;
}, {});
}
我无法真正理解整个代码,特别是!this[a] ? this[a] = true : false;
和新对象({}
)作为filter
的第二个参数传递。
答案 0 :(得分:3)
让我们从filter开始:
filter()方法创建一个包含所有传递元素的新数组 由提供的函数实现的测试。
a
是应用过滤器的数组的随机数。整个要点如下:
return !this[a] ? this[a] = true : false;
如果this[a]
为真,则a
已经处理过一次,并且已作为其属性之一添加到此this[a]
。否则,a
为false。因此,将其否定结果设为true,并返回当前this[a]
。此外,a
将设置为true,然后我们将继续执行下一个filter
。
以下代码段将帮助您了解var numbers = [1,2,3,4,5];
var filteredNumbers = numbers.filter(function(number){
console.log(number);
return number > 2;
});
console.log(filteredNumbers);
的作用:
unique

以下代码段将向您展示function unique ( array ) {
return array.filter(function(a){
console.log(this);
return !this[a] ? this[a] = true : false;
}, {});
}
var array = [1,2,3,1,2,3,4,5,5,6];
console.log(unique(array));
函数中发生的事情:
filter

我理解过滤器的基本逻辑,但我不是{} 作为第二个参数传递,以及每个值如何添加到新数组 用!这[a]
第二个参数是可选值,您可以将其传递给this
方法,并且可以在执行回调时将其用作filter
(检查我在开头提到的关于this
)的链接。你传递一个空对象。在回调中使用关键字{}
时,请引用此对象。这就是为什么代码第一次进入此方法会返回!this[1]
。检查第二个代码段输出的第一行。
我将根据第二个片段解释您问题的第二部分。第一次进入时你有一个空对象(我指的是这个),处理的第一个数字是1.所以这个1将是未定义的。所以?
是真的。因此执行this[1] = true.
后的第一部分是作业
this
现在true
获得了第一个密钥1,其值为!this[1]
。此外,1将从过滤器返回。同样的情况发生在2和3.当我们到达1时
this[1]
是假的,因为private class Scan extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mpd = new ProgressDialog(CatalogActivity.this);
mpd.setTitle(HomeActivity.name);
mpd.setMessage("Searching for items...");
mpd.setIndeterminate(false);
mpd.show();
}
@Override
protected Void doInBackground(Void... voids) {
scanExpression = new DynamoDBScanExpression();
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.CONTAINS)
.withAttributeValueList(new AttributeValue(HomeActivity.id));
scanExpression.addFilterCondition("productId", condition);
result = HomeActivity.mapper.scan(Product.class, scanExpression);
arraylist = new ArrayList<Product>();
for (Product prod : result) {
prod.setName(prod.getName());
prod.setPrice(prod.getPrice());
prod.setProductId(prod.getProductId());
prod.setSummary(prod.getSummary());
prod.setSale(prod.getSale());
prod.setSalePrice(prod.getSalePrice());
arraylist.add(prod);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
lv = (ListView) findViewById(R.id.itemsListView);
adapter = new ListViewAdapter(CatalogActivity.this, arraylist);
lv.setAdapter(adapter);
mpd.dismiss();
}
}
是真的。因此返回false并且现在不会将1添加到将在处理完所有数组元素后返回的数组中。
答案 1 :(得分:2)
基本上,.filter
会通过提供迭代数组的各个值来调用callBack
函数。如果callBack
返回一个解析为true
的值,那么将收集该值,否则将忽略该特定值。
这里使用了filter
的第二个参数。第二个参数将在内部调用this
时用作上下文(callBack
)。因此,在您的代码中,传递的对象将添加数组的值作为每次迭代的属性。在连续迭代中,代码将检查当前值是否在最初传递的对象中作为property
可用。如果可用,则该三元运算符将返回false
,否则返回true
。
因此,将从过滤器函数返回唯一值。
答案 2 :(得分:0)
Array.filter只会在函数传递返回truthy时获取数组的元素。
对于数组的每个元素,它正在执行
return !this[a] // if value is not yet on this
? this[a] = true // add value to this and return true (grab element)
: false; // value was already cached, so return false (don't grab)
所以它只返回每个
中的1个答案 3 :(得分:0)
其他答案基本上解释了这是如何工作的。但有几点:
首先,代替return !this[a] ? this[a] = true : false;
,编写
!this[a] && (this[a] = true)
其次,这个代码有一个缺陷,它只适用于可以作为对象键的元素 - 基本上是字符串或数字。这就是使用Set
更好的原因:
Array.from(new Set(array))
以上内容适用于任何原始或对象。
第三,这种方法对字符串和数字不起作用。如果数字1
存在,则会过滤掉字符串"1"
。
const uniq = a => a.filter(x => !this[x] && (this[x] = true), {});
console.log(uniq([1, '1']));
原因是对象键是字符串值的。
最后,恕我直言,这段代码对于自己的好处来说有点太棘手了。大多数开发人员,即使是经验丰富的开发人员,在弄清楚之前会停下来并抓住他们的头脑。缺乏经验的开发人员必须先查阅thisArg
参数的文档,然后才能理解它Array#filter
。内部分配的三元运算符也有点神秘。我会继续把它写成
if (this[x]) return false;
this[x] = true;
return true;