iT邦幫忙

3

剛接觸JS的新手__ 學習 reduce內做Object的計算

HJ 2019-05-03 00:36:28868 瀏覽

剛學JS的我在codewars上做了一個難度7kyu的題目
題目為 Exes and Ohs
https://ithelp.ithome.com.tw/upload/images/20190502/20117326Tj8pN3VXYr.png

連結如下https://www.codewars.com/kata/exes-and-ohs/javascript

題目是判斷OX的數量是否相等
如果一樣回傳true,不同則false,沒有半個OX也會是true。

好不容易用split解出來後,結果被同學用reduce的解法給驚豔到!
特別寫這篇來記錄一下

解法是用devdocs.io內介紹的一種reduce用法

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) { 
  if (name in allNames) { //如果name這個 Key已經有在allNames裡面了的話
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

出處https://devdocs.io/javascript/global_objects/array/reduce
內的Counting instances of values in an object

裡面的reduce先把allNames設為一個Object,之後用if判斷name這個Key在不在allNames裡面,再去做object給值的動作。

這招沒想到可以用在OX題目上面啊!

上面reduce的結果我用兩種for迴圈再寫了一遍

var ary = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var alname = {};  //存放的Object

//第一種普通的for迴圈寫法
function forFoReduce(ary1){  
  for(var i = 0 ; i < ary1.length ; i++){ 
  //判斷alname的ary1[i]這個 Key的Value是不是NaN,是的話等於一
    if(isNaN( alname[ary1[i]] )){
      alname[ary1[i]] = 1;
    }
    else {
      alname[ary1[i]]++;  //已經等於1了的話就再+1
    }
  }
  return alname;
}

//第二種for迴圈寫法
function forFoReduce2(ary1){
//item是ary1每個陣列內容,就像是上面for迴圈的ary1[i] 
  for(let item of ary1) {     
    if(isNaN( alname[item] )){ //把item當作alname的 Key放進去比對    
      alname[item] = 1;   //Key內的Value是NaN的話就 = 1      
    }
    else {    
      alname[item]++;  //已經找到過了就再加一    
    }
  }
  return alname;
}

以上介紹的三種方法都會產出:
{ 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

了解到這些解法的話再來挑戰一次OX題目吧!
以下私心用for of方式下去解

function XO(str) {
//因為題目給的是字串且有大小寫問題,所以用toUpperCase都先轉成大寫,再用split('')轉成陣列型態。
  var ary = str.toUpperCase().split('');
  var alname = {};   //宣告一個空的Object
    
  for(let item of ary) {
  //如果alname裡面的item這個 Key的Value是NaN的話,等於一
    if(isNaN( alname[item] )){  
      alname[item] = 1;
    }
    else{
      alname[item]++;  //不是NaN就再加一
    }
  }
  return alname.O === alname.X;  //這裡回傳O跟X兩個 Key的Value有沒有一樣
}                                //一樣回傳true反之回傳false

雖然都可以解的出來,但如果追求精簡導致後來的自己看不懂就不好了!


1
fysh711426
iT邦研究生 3 級 ‧ 2019-05-03 21:52:23

我用索引讀取字元~

function XO(str) {
  str = str.toUpperCase();
  var ans = 0;
  for(var i = 0; i < str.length; i++) {
    if (str[i] === 'X')
      ans--;
    if (str[i] === 'O')
      ans++;
  }
  return !ans;
}
HJ iT邦新手 5 級‧ 2019-05-04 12:21:12 檢舉

好厲害
目前只學到用[x][0]抓到字首
沒想到可以這樣用

0
harutsuki
iT邦新手 5 級 ‧ 2019-05-06 19:57:28

map 大概會是這樣

const XO = (str) => {
 str = str.toUpperCase().split('');
 let p = str[0];
 let ans = 0;
 str.map(x => x === p ? ans++ : ans-- )
 return !!!ans
}
HJ iT邦新手 5 級‧ 2019-05-08 11:07:35 檢舉

感覺用map比較簡單欸

0
Gary
iT邦新手 5 級 ‧ 2019-05-07 17:39:30
// 這樣應該好讀易懂吧 (?
function XO(str) {
  return !str.split('').reduce((acc, c) => {
    if (c === 'O' || c === 'o' ) acc++
    if (c === 'X' || c === 'x' ) acc--
    return acc
  }, 0)
}

// 犧牲可讀性的話
const XO = s => !s.split('').reduce(
    (a, c) => ('Oo'.includes(c) ? ++a : 'Xx'.includes(c) ? --a : a)
, 0)
HJ iT邦新手 5 級‧ 2019-05-08 11:06:57 檢舉

驚嘆號原來可以寫在最前面,我都被自己的思維綁住了!

0
dragonH
iT邦大師 1 級 ‧ 2019-05-08 15:52:07

我會先把非x,o的過濾

function XO(str) {
  const strFormat = str.toLowerCase().replace(/[^o,x]/g,'').split('');
  return strFormat.length - strFormat
        .filter(letter => letter === 'x').length * 2 === 0;
}

我要留言

立即登入留言