Javascript 使用回退值减少对象数组

Javascript 使用回退值减少对象数组,javascript,ecmascript-6,lodash,Javascript,Ecmascript 6,Lodash,考虑以下对象: var content = [ { id: 'tab1', langCode: 'en', title: 'rocket' }, { id: 'tab1', langCode: 'da', title: 'raket' }, { id: 'tab2', langCode: 'en', title:

考虑以下对象:

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]);
        }
    }
}
const LOCAL_LANG='da';//为了示例的缘故而硬编码
让localArr=content.filter(item=>item.langCode==LOCAL\u LANG);
if(LOCAL_LANG!=“en”){
让enArr=content.filter(item=>item.langCode=='en');
for(设i=0;i
这样做很有效,但它会创建两个重复的数组,然后以我觉得很笨拙的方式将它们合并在一起。我希望看到一个更优雅的解决方案——最好是一个,在这个解决方案中,我不必多次通过阵列

另一种解决方案(可能稍微干净一点)是在第一次通过时减少
langCode==='da'| | langCode==='en'
上的数组,然后删除重复项。。。但我还是觉得我错过了最明显的解决办法


谢谢

我会将所有内容简化为一个由ID键控的对象,以方便查找,而无需那些额外的
调用:

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

您可以使用一个树来过滤想要的项目

var content=[{id:'tab1',langCode:'en',title:'rocket'},{id:'tab1',langCode:'da',title:'raket'},{id:'tab2',langCode:'en',title:'pen'},{id:'tab2',langCode:'en',title:'pen,
object=object.create(空);
content.forEach(函数(a){
对象[a.id]=对象[a.id]| |{}
对象[a.id][a.langCode]=a;
});		
var result=Object.keys(Object.map(k=>Object[k][Object.keys(Object[k]).filter(l=>l!='en')[0]| |'en');
控制台日志(结果)我会做如下事情

var内容=[
{
id:'表1',
语言代码:“en”,
标题:“火箭”
},
{
id:'表1',
langCode:'da',
标题:'raket'
},
{
id:'表2',
语言代码:“es”,
标题:“boligrafo”
},
{
id:'表2',
语言代码:“en”,
标题:“钢笔”
}
],
结果=内容.排序((a,b)=>a.langCode==“en”?1:-1)
.reduce((p,c)=>p.findIndex(o=>o.id==c.id)==-1?p.concat(c):p,[]);

控制台日志(结果)本地语言的值应优先考虑。您如何知道?我假定英语是后备语言,但对于其他语言,我们如何知道哪一种是本地语言。@NinaScholz我将本地语言存储在一个变量中。我将把它添加到我的示例中。也许你可以添加更多的数据来反映更多的需要。