2017-09-25 62 views
0

編寫一個返回某個activityname的算法。不使用全局變量的遞歸算法的返回值

在我們的功能,我們給出activity的價值,如果我們的數組中存在返回name的價值:

例子:

findMatch('scuba diving', activityItems) = 'Beach' 

const activityItems = [ 
    { 
     name: 'Sunday', 
     items: [ 
      { 
       name: 'Gym', 
       activity: 'weights', 
      }, 
     ], 
    }, 
    { 
     name: 'Monday', 
     items: [ 
      { 
       name: 'Track', 
       activity: 'race', 
      }, 
      { 
       name: 'Work', 
       activity: 'meeting', 
      }, 
      { 
       name: 'Swim', 
       items: [ 
        { 
         name: 'Beach', 
         activity: 'scuba diving', 
        }, 
        { 
         name: 'Pool', 
         activity: 'back stroke', 
        }, 
       ], 
      }, 
     ],  
    }, 
    {} ... 
    {} ... 
]; 

我的實現:

let match = ''; 
const findMatch = (activity, activityItems) => { 
    for (let i = 0; i < activityItems.length; i += 1) { 
     if (activityItems[i].activity === activity) { 
      match = activityItems[i].name; 
      return match; 
     } 

     if (activityItems[i].items && findMatch(activity, activityItems[i].items)) { 
      return match; 
     } 
    } 

    return false; 
}; 

但是我不喜歡我的實現,因爲使用了一個全局變量。有沒有方法可以在沒有它的情況下返回正確的值?

我試過的東西:

const findMatch = (activity, activityItems) => { 
    for (let i = 0; i < activityItems.length; i += 1) { 
     if (activityItems[i].activity === activity) { 
      return activityItems[i].name;    
     } 

     if (activityItems[i].items) { 
      return findMatch(activity, activityItems[i].items); 
     } 
    } 

    return false; 
}; 

但這總是返回false或未定義。

有什麼建議嗎?

回答

1

爲什麼要把這個全局變量放在第一位?只要返回名稱,如果它存在,或者如果不存在,則返回null。請將導致當地變量的遞歸搜索,並且只返回如果不是null

const findMatch = (activity, activityItems) => { 
    for (let i = 0; i < activityItems.length; i++) { 
     if (activityItems[i].activity === activity) 
      return activityItems[i].name; 

     if (activityItems[i].items) { 
      let match = findMatch(activity, activityItems[i].items); 
      if (match) return match; 
     } 
    } 

    return null; 
}; 
1

Array.prototype.find方法內建當發現沒有值返回undefined,所以我爲榜樣通過使用undefined作爲不匹配結果。

我也會用for of來實現你的功能。

const activityItems = [ 
 
    {name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]}, 
 
    {name: 'Monday',items: [{name: 'Track',activity: 'race'}, 
 
     {name: 'Work',activity: 'meeting'}, 
 
     {name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'}, 
 
      {name: 'Pool',activity: 'back stroke'}]}]}, 
 
    {}, 
 
    {} 
 
]; 
 

 
const findMatch = (needle, haystack) => { 
 
    for (let {activity, name, items} of haystack) { 
 
    if (activity == needle) return name; 
 
    if (items && (items = findMatch(needle, items))) return items; 
 
    } 
 
    return undefined; 
 
} 
 

 

 
console.log(findMatch('scuba diving', activityItems))

這也採用解構assingment在for of環抓住你想要的特定屬性。我重用了items變量來分配遞歸調用的結果。您不需要這樣做,但它可以縮短一點,而不必爲此目的而聲明變量。


下面是使用.reduce(),以幫助滿足棉短絨一個版本,但現在我們已經失去了短路:-(。

const activityItems = [ 
 
    {name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]}, 
 
    {name: 'Monday',items: [{name: 'Track',activity: 'race'}, 
 
     {name: 'Work',activity: 'meeting'}, 
 
     {name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'}, 
 
      {name: 'Pool',activity: 'back stroke'}]}]}, 
 
    {}, 
 
    {} 
 
]; 
 

 
const findMatch = (needle, haystack) => { 
 
    return haystack.reduce((res, {activity, name, items}) => 
 
    res !== undefined ? res : 
 
    activity == needle ? name : 
 
    items && findMatch(needle, items) 
 
    , undefined) 
 
} 
 

 

 
console.log(findMatch('scuba diving', activityItems))


還有一個版本,使用功能性技術,而不使用內置的方法。如果功能性編碼是你以後的,我會採用這種方法。

const activityItems = [ 
 
    {name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]}, 
 
    {name: 'Monday',items: [{name: 'Track',activity: 'race'}, 
 
     {name: 'Work',activity: 'meeting'}, 
 
     {name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'}, 
 
      {name: 'Pool',activity: 'back stroke'}]}]}, 
 
    {}, 
 
    {} 
 
]; 
 

 
const findMatch = (needle, haystack) => { 
 
    if (!haystack || !haystack.length) { 
 
    return undefined; 
 
    } 
 
    const {activity, name, items} = haystack[0]; 
 
    return activity == needle ? name : 
 
     findMatch(needle, items) || findMatch(needle, haystack.slice(1)); 
 
} 
 

 
console.log(findMatch('scuba diving', activityItems))


OK,多一個。這是最後一個小變化。由於我們正在討論使用尾遞歸的純粹函數式編程,因此定義將頭部與尾部分開的參數非常有用。 傳播語法其餘語法使這個很容易。

const activityItems = [ 
 
    {name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]}, 
 
    {name: 'Monday',items: [{name: 'Track',activity: 'race'}, 
 
     {name: 'Work',activity: 'meeting'}, 
 
     {name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'}, 
 
      {name: 'Pool',activity: 'back stroke'}]}]}, 
 
    {}, 
 
    {} 
 
]; 
 

 
const findMatch = (needle, head, ...tail) => { 
 
    if (!head) { 
 
    return undefined; 
 
    } 
 
    const {activity, name, items} = head; 
 
    return activity == needle ? name : 
 
     items && findMatch(needle, ...items) || findMatch(needle, ...tail); 
 
} 
 

 
console.log(findMatch('scuba diving', ...activityItems))

+0

eslint錯誤:'迭代器/發電機需要蓄冷器運行時,這也太重量級本指南,使他們。另外,應該避免使用循環來支持數組迭代no-restricted-syntax' – user2456977

+0

+ eslint:由於活動和名稱未被重新分配,因此更改開銷。然後我添加另一個變量,而不是重複使用物品..然後得到錯誤 – user2456977

+0

以上所以必須有一個轉譯參與?什麼「指南」不允許他們,爲什麼?使用轉譯器的關鍵是現在能夠使用有用的新語法功能,而不是爲了避免它們。 「無限制語法」配置表達的意見遠非絕對。我將在一週中的任何一天使用'for for'數組迭代方法。我想我可以重寫這個使用'.reduce()',但我沒有看到任何收益。 – llama