配列を上手く使わないプログラマーはいい人ではない、と私は言いました〜
しばらく前にプロジェクトを引き継ぎました。ロジックがあいまいで、コードが巨大で冗長であるため、開始するのが非常に困難でした。大きな理由は、配列メソッドが熟練していないため、多くのガベージコードが発生するためです。実際、多くの場所は、わずかな変更を加えるだけで、シンプル、効率的、エレガントになります。したがって、ここでは、配列の一般的な方法とキットカットの変態スキルを要約します(キットカットの変態スキルは主に削減されます〜)。
配列操作は最初に注意する必要がありsplice、sort、reverse
、これらの3つの一般的な方法は配列自体に対する操作であり、配列自体を変更することを覚えておいてください。それ自体を変更する他の方法は、追加push/pop/unshift/shift
、削除、塗りつぶし、fill
および複製と塗りつぶしcopyWithin
です。
最初に配列の一般的な方法について説明し、次にそれらを使用することの誤解について説明しましょう。
配列の一般的なメソッド
まず、空に犠牲を払う配列法の怠惰な姿を提示してください!(Array.keys()/Array.values()/Array.entries()
基本を除く):
配列メソッドの百科事典
[1-100]のような配列を生成します。
大量の配列データをテストする場合、次のことができます。
let arr = new Array(100).fill(0).map((item, index) => index + 1)
配列破壊割り当てアプリケーション
// 交换变量
[a, b] = [b, a]
[o.a, o.b] = [o.b, o.a]
// 生成剩余数组
const [a, ...rest] = [...'asdf'] // a:'a',rest: ["s", "d", "f"]
配列の浅いコピー
const arr = [1, 2, 3]
const arrClone = [...arr]
// 对象也可以这样浅拷贝
const obj = { a: 1 }
const objClone = { ...obj }
浅いコピー方法はたくさんありますがarr.slice(0, arr.length)/Arror.from(arr)
、...
演算子を使用した後は他の方法は使いたくないでしょう〜
配列のマージ
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [7, 8, 9]
const arr = [...arr1, ...arr2, ...arr3]
arr1.concat(arr2, arr3)
マージすることもできますが、...
演算子を使用した後は、他の演算子は使用したくないでしょう〜
アレイの重複排除
const arr = [1, 1, 2, 2, 3, 4, 5, 5]
const newArr = [...new Set(arr)]
new Set(arr)
配列パラメーターを受け入れ、セット構造データ型を生成します。セットデータ型の要素は繰り返されず、繰り返されるArray Iterator
ため、この機能を使用して重複を削除できます。
配列の共通部分
const a = [0, 1, 2, 3, 4, 5]
const b = [3, 4, 5, 6, 7, 8]
const duplicatedValues = [...new Set(a)].filter(item => b.includes(item))
duplicatedValues // [3, 4, 5]
配列減算
const a = [0, 1, 2, 3, 4, 5]
const b = [3, 4, 5, 6, 7, 8]
const diffValues = [...new Set([...a, ...b])].filter(item => !b.includes(item) || !a.includes(item)) // [0, 1, 2, 6, 7, 8]
オブジェクトへの配列
const arr = [1, 2, 3, 4]
const newObj = {...arr} // {0: 1, 1: 2, 2: 3, 3: 4}
const obj = {0: 0, 1: 1, 2: 2, length 3}
// 对象转数组不能用展开操作符,因为展开操作符必须用在可迭代对象上
let newArr = [...obj] // Uncaught TypeError: object is not iterable...
// 可以使用Array.form()将类数组对象转为数组
let newArr = Array.from(obj) // [0, 1, 2]
アレイ共通トラバーサル
配列は一般的にトラバースされ、 forEach、every、some、filter、map、reduce、reduceRight、find、findIndex
他の方法もあり、多くの方法で同じ効果を得ることができます。配列メソッドを使用するだけでなく、適切に使用する必要があります。それをうまく使用するには、いつ、どの方法を使用するかを知る必要があります。
トラバーサルの混合使用
filter
map
メソッドの戻り値は引き続き配列であるため、他の配列トラバーサルメソッドと混合できます。トラバースが多いほど、効率が低下することに注意してください〜
const arr = [1, 2, 3, 4, 5]
const value = arr
.map(item => item * 3)
.filter(item => item % 2 === 0)
.map(item => item + 1)
.reduce((prev, curr) => prev + curr, 0)
配列のすべての要素が判定条件を満たしているかどうかを確認します
const arr = [1, 2, 3, 4, 5]
const isAllNum = arr.every(item => typeof item === 'number')
配列のいずれかの要素が判定条件を満たすかどうかを確認します
const arr = [1, 2, 3, 4, 5]
const hasNum = arr.some(item => typeof item === 'number')
基準を満たす最初の要素/添え字を見つける
const arr = [1, 2, 3, 4, 5]
const findItem = arr.find(item => item === 3) // 返回子项
const findIndex = arr.findIndex(item => item === 3) // 返回子项的下标
配列の使用法の誤解
配列には多くの方法があり、多くの方法で同じ効果が得られるため、必要に応じて適切な方法を使用してください。
ガベージコードの主な原因は、配列の一般的なメソッドの不適切な使用です。注意すべき点がいくつかあります。
array.includes()和array.indexOf()
array.includes()
ブール値をarray.indexOf()
返し、配列アイテムのインデックスを返します。indexOf
インデックス値が必要な場合は必ずご利用ください。
const arr = [1, 2, 3, 4, 5]
// 使用indexOf,需要用到索引值
const index = arr.indexOf(1) // 0
if (~index) { // 若index === -1,~index得到0,判断不成立;若index不为-1,则~index得到非0,判断成立。
arr.spilce(index, 1)
}
// 使用includes,不需要用到索引值
// 此时若用indexOf会造成上下文上的阅读负担:到底其他地方有没有用到这个index?
const isExist = arr.includes(6) // true
if (!isExist) {
arr.push(6)
}
array.find()、array.findIndex()和array.some()
array.find()
戻り値は最初の適格な配列アイテムであり、最初の適格な配列アイテムのインデックスがarray.findIndex()
返され、array.some()
複合条件の有無にかかわらず、リターンtrue
がある場合は、リターンがない場合はアイテムが返されfalse
ます。これらの3つは短絡操作であることに注意してください。つまり、適格なものを見つけた後、トラバーサルは続行されません。
配列array.find()
のサブアイテムarray.findIndex()
が必要な場合、サブアイテムのインデックス値 が必要な場合、および条件を満たす必要があるサブアイテムのみを知る必要がある場合に使用し array.some()
ます。
const arr = [{label: '男', value: 0}, {label: '女', value: 1}, {label: '不男不女', value: 2}]
// 使用some
const isExist = arr.some(item => item.value === 2)
if (isExist) {
console.log('哈哈哈找到了')
}
// 使用find
const item = arr.find(item => item.value === 2)
if (item) {
console.log(item.label)
}
// 使用findIndex
const index = arr.findIndex(item => item.value === 2)
if (~index) {
const delItem = arr[index]
arr.splice(index, 1)
console.log(`你删除了${delItem.label}`)
}
ブール値のみが必要な場合、および配列項目が文字列または数値である場合に使用することをお勧めします array.some()
:
// 当子包含数字0的时候可能出错
const arr = [0, 1, 2, 3, 4]
// 正确
const isExist = arr.some(item => item === 0)
if (isExist) {
console.log('存在要找的子项,很舒服~')
}
// 错误
const isExist = arr.find(item => item === 0)
if (isExist) { // isExist此时是0,隐式转换为布尔值后是false
console.log('执行不到这里~')
}
// 当子项包含空字符串的时候也可能出错
const arr = ['', 'asdf', 'qwer', '...']
// 正确
const isExist = arr.some(item => item === '')
if (isExist) {
console.log('存在要找的子项,很舒服~')
}
// 错误
const isExist = arr.find(item => item === '')
if (isExist) { // isExist此时是'',隐式转换为布尔值后是false
console.log('执行不到这里~')
}
array.find()和array.filter()
array.filter()
返されるのはすべての適格なサブアイテムの配列であり、すべての配列がトラバースされることを知っておいてください 。 array.find()
最初の適格なサブアイテムのみが返されます。これは短絡操作です。これ以上の例はありません〜
セットデータ構造の合理的な使用
es6はネイティブにSet
データ構造を提供するため Set
、サブアイテムが繰り返されないようにすること ができ、配列で変換するのに非常に便利です。したがって、繰り返し加算を伴うシナリオでは、Set
代わりArray
に直接使用 して 、複数を回避できます。既存の子かどうかを繰り返し判断する場所。
const set = new Set()
set.add(1)
set.add(1)
set.add(1)
set.size // 1
const arr = [...set] // arr: [1]
強力な削減
array.reduce
現在のコールバック関数の戻り値をトラバースして、次のコールバック関数実行の最初のパラメーターとして使用します。
array.reduce
複数回トラバースする必要がある一部のシーンを置き換えるために使用すると 、コード操作の効率を向上させることができます。
次のようにarr
、文字「s」と各要素の数値で構成される配列があり、その中で最大の数値を見つけたとします:(arr
空ではない)
const arr = ['s0', 's4', 's1', 's2', 's8', 's3']
// 方法1 进行了多次遍历,低效
const newArr = arr.map(item => item.substring(1)).map(item => Number(item))
const maxS = Math.max(...newArr)
// 方法2 一次遍历
const maxS = arr.reduce((prev, cur) => {
const curIndex = Number(cur.replace('s', ''))
return curIndex > prev ? curIndex : prev
}, 0)
const arr = [1, 2, 3, 4, 5]
// 方法1 遍历了两次,效率低
const value = arr.filter(item => item % 2 === 0).map(item => ({ value: item }))
// 方法1 一次遍历,效率高
const value = arr.reduce((prev, curr) => {
return curr % 2 === 0 ? [...prev, curr] : prev
}, [])
また、reduceを使用して次の処理を実行し、目的のhtml構造を生成することもできます。
// 后端返回数据
const data = {
'if _ then s9': [
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生',
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生',
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生'
],
'if C then s4': [
'当有条件时时,结构构件满足要求,要求属于安全性、适用性和耐久性',
'当有条件时时,住宅结构满足要求,要求属于安全性、适用性和耐久性'
]
}
const ifthens = Object.entries(data).reduce((prev, cur) => {
const values = cur[1].reduce((prev, cur) => `${prev}<p>${cur}</p>`, '')
return `
${prev}
<li>
<p>${cur[0]}</p>
${values}
</li>
`
}, '')
const html = `
<ul class="nlp-notify-body">
${ifthens}
</ul>
`
生成されるhtml構造は次のとおりです。
<ul class="nlp-notify-body">
<li>
<p>if _ then s9</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
</li>
<li>
<p>if C then s4</p>
<p>当有条件时时,结构构件满足要求,要求属于安全性、适用性和耐久性</p>
<p>当有条件时时,住宅结构满足要求,要求属于安全性、适用性和耐久性</p>
</li>
</ul>