2017-05-31 68 views
0

我在尋找一種智能的方式reoganise裏面由數組元素: 在進入我有:組織元素的數組中

[{"name": "brevet", 
"country": "fr" 
},{ 
"name": "bac", 
"country": "fr" 
},{ 
"name": "des", 
"country": "ca" 
},{ 
"name": "dep", 
"country": "ca" 
}{ 
"name": "other",, 
"country": "other"}] 

我希望重新組織按國家我的陣列有這在我的輸出:

[{ 
    "name": "fr", 
    "degrees": [ 
    { 
     "name": "brevet", 
     "country": "fr" 
    },{ 
     "name": "bac", 
     "country": "fr" 
    }] 
},{ 
    "name": "ca", 
    "degrees": [{ 
     "name": "des", 
     "country": "ca" 
    },{ 
     "name": "dep", 
     "country": "ca" 
    }] 
},{ 
    "name": "other", 
    "degrees": [{ 
     "name": "other", 
     "country": "other" 
    }] 
}] 

爲此,我寫了一個骯髒的功能,但在我看來有一個更好的辦法,但我不知道如何。如果有人能在一個更好的方式來做到這一點LIGTH我的大腦,我會是有益的

private organizeDegrees(degrees: Array<SubscriptionFieldInterface>) { 
let degreesByCountry = new Array(); 
let storeIndex = new Array(); 
degrees.map(degree => { 
    let index = null; 
    storeIndex.find((element, idx) => { 
    if (element === degree.country) { 
     index = idx; 
     return true; 
    } 
    }); 
    if (index === null) { 
    index = degreesByCountry.length; 
    let newEntry = { 
     'name': degree.country, 
     'degrees': new Array() 
    }; 
    storeIndex.push(degree.country); 
    degreesByCountry.push(newEntry); 
    } 
    degreesByCountry[index].degrees.push(degree); 
}); 
return degreesByCountry; 
} 

感謝的

+0

這是以下,更 「分組」, 「由排序」。 – evolutionxbox

回答

1

可以組使用Object.keys數組和映射對象:

var groupBy = function(xs, key) { 
    return xs.reduce(function(rv, x) { 
    (rv[x[key]] = rv[x[key]] || []).push(x); 
    return rv; 
    }, {}); 
}; 

var grouped = groupBy(array, "country"); 

var mappedArray = Object.keys(grouped).map(key => ({name: key, degrees: grouped [key]})); 
+0

Object.values'映射更容易 – Slim

+0

Object.values非常新,支持非常有限。 – Saravana

+0

我感謝這個快速回復。我使用Object.keys的例子,因爲我的版本的Typescript Object.value不起作用。但我很高興問這個問題,因爲你給了我有用的回答,現在我重新考慮我的所有腳本。 –

0

而且還有一種方法:

arr = [ /* your array */ ]; 

arr = Object.values(arr.reduce((ac, el) => { 
    if(!ac[el.country]) ac[el.country] = {"name": el.country, "degrees": []} 

    ac[el.country].degrees.push(el); 

    return ac 
}, {})) 

console.log(arr) // formated 
0

另一種解決方案,它也處理'id'=>'@id'mapping:

const a = [{"name":"brevet","country":"fr"},{"name":"bac","country":"fr"},{"id":73,"name":"des","country":"ca"},{"name":"dep","country":"ca"},{"name":"other","country":"other"}]; 
 

 
const r = [...new Set(a.map(({country}) => country))] // list of unique country names 
 
    .map(c => Object.assign({name: c}, // for each country 
 
    {degrees: a.filter(x => x.country === c).map(y => Object.keys(y).includes('id') // handle 'id' => '@id' mutation 
 
     ? {'@id': "/subscription_fields/" + y.id, name: y.name, country: y.country} 
 
     : y) 
 
    })) 
 

 
console.log(r)

0

這純粹是ES6,而且相當簡潔的,但可能的可讀性。此外,它不會添加「@id」:「/ subscription_fields/83」,它可以作爲後處理:

const groupByKey = (arr, key) => [...arr.reduce((acc, deg) => 
    acc.set(deg[key], {name: deg[key], degrees: [ ...(acc.get(deg[key]) || {degrees: []}).degrees, deg]}) 
, new Map()).values()]; 

console.log(groupByKey(degrees, 'country')); 
0

你可以使用一個哈希表,並收集對象中的所有值。爲了獲得結果數組,你只需要推一次對象。

var data = [{ name: "brevet", country: "fr" }, { name: "bac", country: "fr" }, { id: 73, name: "des", country: "ca" }, { name: "dep", country: "ca" }, { name: "other", country: "other" }], 
 
    result = data.reduce(function (hash) { 
 
     return function (r, a) { 
 
      if (!hash[a.country]) { 
 
       hash[a.country] = { name: a.country, degrees: [] }; 
 
       r.push(hash[a.country]); 
 
      } 
 
      hash[a.country].degrees.push({ name: a.name, country: a.country }); 
 
      return r; 
 
     }; 
 
    }(Object.create(null)), []); 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }