使用回退值减少对象数组

时间:2016-10-10 20:47:15

标签: javascript ecmascript-6 lodash

考虑以下对象:

var content = [
    {
        id: 'tab1',
        langCode: 'en',
        title: 'rocket'
    },
    {
        id: 'tab1',
        langCode: 'da',
        title: 'raket'
    },
    {
        id: 'tab2',
        langCode: 'en',
        title: 'factory'        
    },
    {
        id: 'tab3',
        langCode: 'es',
        title: 'boligrafo'
    },      
];

我想将这个数组减少到一个具有以下限制的新数组:

  • 没有重复的ID
  • 本地语言的值应优先考虑
  • 如果没有本地翻译,请回到英文
  • 应丢弃所有其他翻译(即使他们有唯一的ID)

这意味着,如果当地语言是丹麦语,则上述数据的输出如下:

[
    {
        id: 'tab1',
        langCode: 'da',
        title: 'raket'
    },
    {
        id: 'tab2',
        langCode: 'en',
        title: 'factory'        
    },
];

我的目标是让代码尽可能简短易读,并且我完全可以使用ES6和Lodash。这就是我到目前为止所做的:

const LOCAL_LANG = 'da'; // Hard coded for the sake of the example

let localArr = content.filter(item => item.langCode === LOCAL_LANG);

if(LOCAL_LANG !== 'en) {
    let enArr = content.filter(item => item.langCode === 'en');
    for (let i = 0; i < enArr.length; i++) {
        if (!_.find(localArr, { 'id': enArr[i].id})) {
            localArr.push(enArr[i]);
        }
    }
}

这样可以解决问题,但它创建了两个重复的数组,然后将它们合并在一起,我认为这是一种块状的方式。我希望看到一个更优雅的解决方案 - 最好是一个,我不需要多次传递数组。

另一种(也许是稍微清洁一点)的解决方案是在第一次通过时减少langCode === 'da' || langCode === 'en'上的数组,然后删除重复...但我只是觉得我错过了最明显的解决方案

谢谢!

3 个答案:

答案 0 :(得分:1)

我会将所有内容缩减为由ID键入的对象,以便在没有额外_.find次调用的情况下轻松查找:

const targetLang = 'da';
const fallbackLang = 'en';

const itemsByKey = content.reduce((allItems, item) => {
  if (item.langCode === targetLang 
      || (!(item.id in allItems) && item.langCode === fallbackLang)) 
  {
    return Object.assign(allItems, { [item.id]: item });
  } else {
    return allItems;
  }
}, {});

此解决方案只需要对原始数组进行一次传递。如果您需要将此查找对象转换回数组,则需要第二次传递:

var normalizedArray = Object.keys(itemsByKey).map(key => itemsByKey[key]);

答案 1 :(得分:1)

您可以使用树并过滤所需的项目。

&#13;
&#13;
  <connectionStrings>
    <add name="MyDbContextConnectionString" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;UserId=root;Password=toor;database=gilbert_sip;CharSet=utf8;Persist Security Info=True"/>
  </connectionStrings>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

我会这样做。

var content = [
    {
        id: 'tab1',
        langCode: 'en',
        title: 'rocket'
    },
    {
        id: 'tab1',
        langCode: 'da',
        title: 'raket'
    },
    {
        id: 'tab2',
        langCode: 'es',
        title: 'boligrafo'
    },
    {
        id: 'tab2',
        langCode: 'en',
        title: 'pen'
    }
],
result = content.sort((a,b) => a.langCode === "en" ? 1 : -1)
                .reduce((p,c) => p.findIndex(o => o.id === c.id) === -1  ? p.concat(c) : p,[]);
console.log(result);