Day 3 - Array 阵列组合技 (2)

前言

前一篇介绍了 forEachfiltermapreduce,算是平常我比较常使用,而且在很多情况可以通用的阵列组合技了。

今天来讲的,是比较针对特定情境的功能,会在很多脑袋卡住的时候突然「啊哈!」想到的 method。

各种 Method 的实战

今天来看看以下这几个 array 常用的 method:

  • includes / indexOf / splice
  • some / every
  • sort

includes / indexOf / splice

includes() 方法会判断阵列是否包含特定的元素,并以此来回传 true 或 false。(参考 MDN)

arr.includes(searchElement[, fromIndex])

indexOf() 方法会回传给定元素於阵列中第一个被找到之索引,若不存在於阵列中则回传 -1。(参考 MDN)

arr.indexOf(searchElement[, fromIndex])

splice() 方法可以藉由删除既有元素并/或加入新元素来改变一个阵列的内容。(参考 MDN)

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

这组 combo 带有一种「针对某个人」的感觉(霸凌?)

  • includes:单纯用来判断是否包含某个人
  • indexOf:不只判断是否包含某个人,还找到在哪个位置
  • splice:可以在指定位置新增或删掉某个人

✔ Checkbox 勾选


实战上可以应用在表单内的 checkbox,我们会自己保存一个 checked 的阵列,代表有勾选的项目。

当我们点击原本不在阵列中的东西时,会透过 includes 发现并用 push 加进去;反之,如果原本就在阵列中,会透过 indexOf 找到是在哪个位置,接着用 splice 将该位置抽掉。

const checked = [?, ?, ?];

const onChanged = (item) => {
    if (checked.includes(item)) {
        const itemIndex = checked.indexOf(item);
        checked.splice(itemIndex, 1);
    } else {
        checked.push(item);
    }
};

console.log(checked); // [?, ?, ?]

// 这边模拟点击的效果
onChanged(?);
console.log(checked); // [?, ?]
onChanged(?);
console.log(checked); // [?, ?, ?]

✅ some / every

some() 方法会透过给定函式、测试阵列中是否至少有一个元素,通过该函式所实作的测试。(参考MDN)

arr.some(callback[, thisArg])

every() 方法会测试阵列中的所有元素是否都通过了由给定之函式所实作的测试。(参考MDN)

arr.every(callback[, thisArg])

原本用 for 回圈会搭配 break 来提升效率,但如果只是单纯用回圈来做判断,使用 some()every() 可以用更少的 code 做到一样的事情,并且提升可读性。

两者的差异:

  • some(): 阵列中至少一个符合就回传 true
  • every(): 阵列中至少一个符合就回传 false

题外话,这对组合真的很像太极上面的黑与白啊!

✔ 用 some() 判断「检核错误」

const fields = [
    { name: 'Allen', error: false },
    { password: 'Gx45Fa', error: false },
    { email: 'abcdgmail.com', error: true },
    { phone: '0912345678', error: false }
];
// 只要任何一个栏位有 error,整体而言就是错误
const invalid = fields.some(field => field.error);
// 可以改用 every() 反向来写,但这个 case 用 some() 比较好读
const invalid2 = !fields.every(field => !field.error);

if (invalid) {
    console.log('请检查栏位是否正确');
}

执行结果

请检查栏位是否正确

✔ 用 every() 判断是否「全选」

const options = [
    { icon: ?, checked: true },
    { icon: ?, checked: true },
    { icon: ?, checked: false },
    { icon: ?, checked: true }
];
let allChecked = false;

const onChanged = (item) => {
    const foundOption = options.find(option => option.icon === item);
    foundOption.checked = !foundOption.checked;
    
    // 每个选项都有勾选的话,就可以让「全选」勾选
    allChecked = options.every(option => option.checked);
    // 可以改用 some() 反向来写,但这个 case 用 every() 比较好读
    allChecked = !options.some(option => !option.checked);
    
    if (allChecked) {
        console.log('全选!');
    }
};

// 这边模拟点击的效果
onChanged(?);

执行结果

全选!

✅ sort

sort() 方法会原地(in place)对一个阵列的所有元素进行排序,并回传此阵列。(参考 MDN)

arr.sort([compareFunction])

sort 的用法很单纯,就是排序。但因为可以带一个 function 当作参数,就能够做到复杂,甚至客制化的排序:

✔ 基础版(不带参数,根据 Unicode 排序)

const arr = ['Jack', 'Allen', 'Alice', 'Susan'];
arr.sort();
console.log(arr);

执行结果

["Alice", "Allen", "Jack", "Susan"]

✔ Array of object 排序(指定 property)

可以直接拿阵列里每个 object 中的指定 property 来排序,会需要帮 sort 带一个函式当参数,如果是 number,可以回传相减的结果,因为回传正、负数会让排序结果不同。

const arr = [
    { name: 'Jack', score: 70 },
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Susan', score: 90 }
];
// 升幂 用 a.score - b.score
// 降幂 用 b.score - a.score
arr.sort((a, b) => a.score - b.score);
console.log(arr); 

执行结果

[
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Jack', score: 70 },
    { name: 'Susan', score: 90 }
]

✔ 指定排序顺序(搭配 indexOf())

indexOf 是 array 的其中一个 method,可以搜寻指定子元素在阵列中的索引(index),若找不到则回传 -1,详细可参考 MDN

这种比较会用在,存资料的时候没有按照顺序,但显示资料时却要按照指定的顺序

const arr = [
    { name: 'Jack', score: 70 },
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Susan', score: 90 }
];
// 指定排序顺序要按照这样
const arrOrder = ['Susan', 'Allen', 'Jack', 'Alice'];

arr.sort((a, b) => (arrOrder.indexOf(a.name) < arrOrder.indexOf(b.name) ? -1 : 1));

console.log(arr); 

执行结果

[
    { name: 'Susan', score: 90 },
    { name: 'Allen', score: 50 },
    { name: 'Jack', score: 70 },
    { name: 'Alice', score: 60 }
];

结语

array 还有非常多好用的 method 可以用,可以参考 MDN,虽然用法我们都看得懂,但实战才是最重要的(跟考驾照一样?),而这些通常也不会有人特地写文章介绍,而是要从长年看 code、用 code 的过程中体验,并且把好的使用情境记下来。

因此如果有机会看到其他人写的 code,真的是有很多地方可以观摩学习,而且通常要搭配情境(context)比较好理解,才会在写 code 的过程中信手拈来。

漫天星点
在每一个连结与跨越
化作指引的星辉

参考资料

Array MDN


<<:  Day04 如何通讯-网路协商

>>:  D04 - 从零开始的 Firmata 通讯

【Day6】Props和States之间到底是什麽关系!? 怎麽传怎麽用咧..? o_O ||

这篇要来谈React的states跟Props States跟Props可以看作是React里面的A...

【後转前要多久】# Day06 CSS - Selectors 选取器

CSS Selectors 介绍 Selectors英文直接翻译是选择者、选择的物品等等,中文叫 选...

Day12 Redis应用实战-String操作

启动Redis Server # 复制安装档内的redis.conf 到自己指定的路径下 cp /h...

【心得】checkbox表单实作-待办清单

上一次介绍了各种表单的使用 那麽实战练习必不可少呀! 今天就演练演练自制待办清单吧 首先来看一下想做...

110/11 - 把照片储存在Pictures/应用程序名称资料夹 - 1

不太可能每个专案都那麽爽,可以把相片储存在内部储存空间/Android/data/packageNa...