面試題數組去重引出的多元宇宙😏

javascript.gif

1.怎麼解決一個數組去重問題

我看了不少面試相關的問題,發現數組去重出現過幾回,這裏就對數組去重問題進行一個總結。而且進行擴展。請必定要看到第二章!javascript

問題描述:數組去重,顧名思義就是,把數組裏的重複數值去除,使其多個相同的數值變爲一個,最後使數組裏不含有重複數值。html

舉個例子:有個數組:[1,2,3,4,4,5,5,5,6,7],數組去重後就變爲[1,2,3,4,5,6,7]java

該問題有不少解決方法,這裏將一一列出,而且會對其個別重要知識點進行擴展web

解法將由淺入深😏,必定要看到最後幾個解法!面試

🤔 解法1:

使用雙重for和splicesegmentfault

// 雙重for加splice
function unique(arr){            
    for(var i=0; i<arr.length; i++){
        for(var j=i+1; j<arr.length; j++){
            if(arr[i]==arr[j]){         
            //第一個等同於第二個,splice方法刪除第二個
                arr.splice(j,1);
                j--;
            }
        }
    }
return arr;
}
複製代碼

🤔 解法2

使用indexof方法和新數組數組

//使用indexof
function unique(arr) {
    var array = [];//用新數組來裝
    for (let i = 0; i < arr.length; i++) {
        if (array.indexOf(arr[i]) === -1) {
            //indexof返回-1表示在新數組中不存在該元素
            array.push(arr[i])//是新數組裏沒有的元素就push入
        }
    }
    return array;
}
複製代碼

使用includes也能夠判斷是否含有某值markdown

function unique(arr) {
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes(arr[i]) ) {
            //includes 檢測數組是否有某個值
                    array.push(arr[i]);
              }
    }
    return array
}
複製代碼
  • indexOf()方法返回在數組中能夠找到一個給定元素的第一個索引,若是不存在,則返回-1。有兩個參數,第一個參數是要查找的元素,第二個參數可選,是開始查找的位置。若是該索引值大於或等於數組長度,意味着不會在數組裏查找,返回-1。若是參數中提供的索引值是一個負值,則將其做爲數組末尾的一個抵消,即-1表示從最後一個元素開始查找,-2表示從倒數第二個元素開始查找,查找順序仍然是從前向後查詢數組。若是抵消後的索引值仍小於0,則整個數組都將會被查詢。其默認值爲0數據結構

  • includes() 方法用來判斷一個數組是否包含一個指定的值,根據狀況,若是包含則返回 true,不然返回false。其也有兩個參數,第一個是要查找的元素,第二個可選,是開始查找的位置,與indexof相同的是,第二個參數爲負值的話,就從末尾開始往前跳 參數 的絕對值個索引,而後日後搜尋。默認爲 0svg

🤔 解法3

使用sort方法先排序,使相同的元素都相鄰

function unique(arr) {
    arr = arr.sort((a, b) => a - b)//sort先按從小到大排序
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
複製代碼

sort方法用於從小到大排序(返回一個新數組),其參數中不帶以上回調函數就會在兩位數及以上時出現排序錯誤(若是省略,元素按照轉換爲的字符串的各個字符的Unicode位點進行排序。兩位數會變爲長度爲二的字符串來計算)。因此本身要寫一個排序標準,當回調函數返回值大於0時兩個值調換順序。

🤔 解法4

ES6 提供了新的數據結構 Set。Set能夠很是簡單的去重

function unique(arr) {
    const result=new Set(arr);
    return [...result];
    //使用擴展運算符將Set數據結構轉爲數組
}
複製代碼

Set對象是值的集合,你能夠按照插入的順序迭代它的元素。 Set中的元素只會出現一次,即 Set 中的元素是惟一的。

🤔 解法5

使用Map

function unique(arr) {
    let map = new Map();
    let array = new Array();  // 數組用於返回結果
    for (let i = 0; i < arr.length; i++) {
      if(map.has(arr[i])) {  // 若是有該key值
        map.set(arr[i], true); 
      } else { 
        map.set(arr[i], false);   // 若是沒有該key值
        array.push(arr[i]);
      }
    } 
    return array ;
}
複製代碼

Map 對象保存鍵值對,而且可以記住鍵的原始插入順序。任何值(對象或者原始值) 均可以做爲一個鍵或一個值。

  • Map.prototype.has(key) 返回一個布爾值,表示Map實例是否包含鍵對應的值。
  • Map.prototype.set(key, value) 設置Map對象中鍵的值。返回該Map對象。

🤔 解法6

使用filter

function unique(arr) {
    return arr.filter(function (item, index, arr) {
        //當前元素,在原始數組中的第一個索引==當前索引值,不然返回當前元素
        //不是那麼就證實是重複項,就捨棄
        return arr.indexOf(item) === index;
    })
}
複製代碼

filter英文意思是篩選,filter() 方法建立一個新數組, 其包含經過所提供函數實現的測試的全部元素。其回調函數包含三個參數(數組中當前正在處理的元素,在處理的元素在數組中的索引(可選),調用了 filter 的數組自己(可選))

🤔 解法7

使用reduce加includes

function unique(arr){
    let result=arr.reduce((acc,cur)=>{
        if(!acc.includes(cur)){
            acc.push(cur);
        }
        return acc;
    },[])//[]做爲回調函數的第一個參數的初始值
    return result
}
複製代碼

2.數組去重解法7引出關於reduce的另外一道面試題

reduce的用處不少,很重要,這裏補上上面對reducer的知識點解釋。

reduce介紹

MDN中對其的描述是:reduce() 方法對數組中的每一個元素執行一個由您提供的reducer函數(升序執行),將其結果彙總爲單個返回值。其能作的功能不少,經過回調函數實現。

reduce的第一個參數是個回調函數,其有四個參數(累加器,當前值,當前索引,原數組),後兩個參數可選。第二個參數是回調函數的第一個參數累加器的初始值(很重要)

注意:不給初始值,那麼初始值就是原數組的第一個元素,計算從第二個元素開始。給了初始值就是從第一個元素開始

經過代碼實現功能瞭解reduce與其回調函數的書寫:

  • 爲存儲數值的數值進行累加求和
let result=[1,2,3,4].reduce((acc,cur)=>{
    return acc+cur;//acc爲累加器(初始值爲數組第一個元素),cur爲當前元素
})
console.log(result);//輸出10
//由於沒初始值,因此從數組第二個元素開始計算,因此處理上面數組,回調函數共運行了3次
複製代碼
  • 累加求和時給初始值
let result=[1,2,3,4].reduce((acc,cur,index,o)=>{
    return acc+cur;
},10)
console.log(result);//輸出20
//由於有初始值,因此從數組第一個元素開始計算,因此處理上面數組,回調函數共運行了4次
複製代碼
  • 按屬性對object進行分類
const bills=[{type:'transfer',momey:233},
             {type:'study',momey:341},
             {type:'shop',momey:821},
             {type:'transfer',money:821},
             {type:'study',momey:821}
            ]
let result=bills.reduce((acc,cur)=>{
    if(!acc[cur.type]){//遇到不存在的類型,就新建一個空數組來裝
        acc[cur.type]=[];//二維數組
    }
    acc[cur.type].push(cur)
    return acc;
},[])//爲累加器設置初始值爲空數組,做爲分類用的容器
console.log(result);
//輸出
[
  transfer: [{ type: 'transfer', momey: 233 },{ type: 'transfer', money: 821}],
  study: [ { type: 'study', momey: 341 }, { type: 'study', momey: 821 } ],
  shop: [ { type: 'shop', momey: 821 } ]
]
複製代碼

reduce相關面試題

🤔 題目描述:請使用原生 JavaScript 實現一個方法,判斷 html 中出現次數最多的標籤,並統計這個次數。

知識點細化:

  • 獲取全部標籤:

    document.querySelector(*):列出頁面內全部標籤,*表示選擇器*,也就是所有。

  • Object.entries():

    Object.entries()返回一個數組,其元素是與直接在object上找到的可枚舉屬性鍵值對相對應的數組。屬性的順序與經過手動循環對象的屬性值所給出的順序相同。簡單的來講就是能夠把對象的每一個屬性變爲一個數組,這個數組裏有兩個值,一個爲屬性名,一個爲屬性值。例如:Object.entires({a:1,b:2,c:3})會獲得[ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]

思路分析:
1. 先得到含有全部標籤的NodeList數組,而後將其加工爲只有標籤名的數組,接着使用reduce獲得一個對象,以標籤名爲屬性名,標籤數量爲屬性值的對象。
2.將上一步獲得的對象用Object.entires()變爲個二維數組,再使用reduce對其處理,獲得數量最多的那個標籤(比較每一個數組的tags[1],返回數組的tags[0])。

答案代碼:

window.onload=function(){
    // 最大數的思路是JS 必考的 使用reduce
    const maxBy=function(list,tag){
        return list.reduce(
            function(x,y){
                //根據reduce方法得到數量最大的那個標籤
                return tag(x)>tag(y)?x:y
            }
            )
    }
    function getFrequentTag(){
        //獲得reduce 須要的數組
        const tags=[...document.querySelectorAll('*')].map(x=>x.tagName).reduce((acc,tag)=>{
            acc[tag]=acc[tag]?acc[tag]+1:1;
            //數組存在該元素,就值+1,不然建立元素,設置值爲1
            return acc;//獲得以tag名爲屬性名,數量爲屬性值的對象
        },{})//初始值爲對象
        return maxBy(Object.entries(tags),tag=>tag[1])
        //tag=>tag[1]這個函數表示return數組的第二個值,也就是標籤的數量
    }
    console.log(getFrequentTag());
}
複製代碼

擴展:如何獲得第二多的標籤,以及數量第X大的標籤呢?

對上面的解法進行進一步的優化,咱們要作的不在是獲得最大,而是要獲得任意大的標籤!
使用sort方法改進,對list數組進行排序,再到list數組中取相應位置的數值。

代碼:

//得到第X多的標籤

window.onload=function(){
    // 最大數的思路是JS 必考的 使用reduce
    const maxByx=function(list,tag,x){
        list=list.sort((a,b)=>{
            return tag(b)-tag(a);//數量從大到小排序
        })
        return list[x];
    }
    function getFrequentTag(){
        //獲得reduce 須要的數組
        const tags=[...document.querySelectorAll('*')].map(x=>x.tagName).reduce((acc,tag)=>{
            acc[tag]=acc[tag]?acc[tag]+1:1;//數組存在該元素,就值+1,不然建立元素,設置值爲1
            return acc;//獲得以tag名爲屬性名,數量爲屬性值的對象
        },{})//初始值爲對象
        return maxByx(Object.entries(tags),tag=>tag[1],1)
        //第三個參數用於指定要第幾大的,這裏指定第二大的
        //tag=>tag[1]這個函數表示return數組的第二個值,也就是標籤的數量
    }
    console.log(getFrequentTag());
}
複製代碼

根據上面代碼return maxByx(Object.entries(tags),tag=>tag[1],1),咱們只須要指定第三個參數值就可以獲得咱們要的數量排名第X的的那個標籤。
這裏就完成了面試中對獲得html中最大數量標籤的昇華了!

感謝閱讀,有好的建議請必定提出,感謝感謝,筆者最近也在準備面試中!

參考文章:

如何獲取頁面出現次數最多的 HTML 標籤

JavaScript數組去重

相關文章
相關標籤/搜索