【问题标题】:Reducing object array with fallback values减少具有后备值的对象数组
【发布时间】:2017-02-19 08:38:32
【问题描述】:

考虑以下对象:

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' 上的数组,然后删除重复项......但我仍然觉得我错过了最明显的解决方案。

谢谢!

【问题讨论】:

  • 应该优先考虑本地语言的值你怎么知道的?
  • 我认为英语是备用语言,但对于其余的我们如何知道哪一种是当地语言。
  • @NinaScholz 我将本地语言存储在一个变量中。我会将它添加到我的示例中。
  • 也许您添加更多数据以反映您的更多需求。

标签: javascript ecmascript-6 lodash


【解决方案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]);

【讨论】:

    【解决方案2】:

    您可以使用树并过滤想要的项目。

    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' }],
        object = Object.create(null);
    
    content.forEach(function (a) {
        object[a.id] = object[a.id] || {}
        object[a.id][a.langCode] = a;
    });		
    
    var result = Object.keys(object).map(k => object[k][Object.keys(object[k]).filter(l => l !== 'en')[0] || 'en']);
    
    console.log(result);

    【讨论】:

      【解决方案3】:

      我会这样做。

      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);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-26
        • 2018-01-05
        • 2018-09-03
        • 2020-12-30
        • 1970-01-01
        • 1970-01-01
        • 2018-04-15
        相关资源
        最近更新 更多