基本的な配列クラスには.map
、.forEach
、.filter
、.reduce
、 だが .groupBy
不在のため、次のようなことができません
const MyComponent = (props:any) => {
return (
<div>
{
props.tags
.groupBy((t)=>t.category_name)
.map((group)=>{
[...]
})
}
</div>
)
}
私は自分で何かを実装することになりました:
class Group<T> {
key:string;
members:T[] = [];
constructor(key:string) {
this.key = key;
}
}
function groupBy<T>(list:T[], func:(x:T)=>string): Group<T>[] {
let res:Group<T>[] = [];
let group:Group<T> = null;
list.forEach((o)=>{
let groupName = func(o);
if (group === null) {
group = new Group<T>(groupName);
}
if (groupName != group.key) {
res.Push(group);
group = new Group<T>(groupName);
}
group.members.Push(o)
});
if (group != null) {
res.Push(group);
}
return res
}
だから今できる
const MyComponent = (props:any) => {
return (
<div>
{
groupBy(props.tags, (t)=>t.category_name)
.map((group)=>{
return (
<ul key={group.key}>
<li>{group.key}</li>
<ul>
{
group.members.map((tag)=>{
return <li key={tag.id}>{tag.name}</li>
})
}
</ul>
</ul>
)
})
}
</div>
)
}
かなりうまくいきますが、メソッド呼び出しをチェーンするだけではなく、リストをラップする必要があるのは残念です。
より良い解決策はありますか?
あなたはあなたのアプリの配列プロトタイプに関数を追加することができます(これをお勧めしない人もいることに注意してください: なぜネイティブオブジェクトを拡張することは悪い習慣ですか? ):
Array.prototype.groupBy = function(/* params here */) {
let array = this;
let result;
/* do more stuff here*/
return result;
};
次に、次のようにTypeScriptでインターフェイスを作成します。
.d.tsバージョン:
interface Array<T>
{
groupBy<T>(func:(x:T) => string): Group<T>[]
}
または通常のtsファイルで:
declare global {
interface Array<T>
{
groupBy<T>(func:(x:T) => string): Group<T>[]
}
}
それからあなたは使うことができます:
props.tags.groupBy((t)=>t.category_name)
.map((group)=>{
[...]
})
良いオプションはlodash
かもしれません。
npm install --save lodash
npm install --save-dev @types/lodash
インポートするだけですimport * as _ from 'lodash'
と使用します。
例
_.groupBy(..)
_.map(..)
_.filter(..)