2017-08-04 49 views
0

我想將羣組中的所有消息分組(聊天)。無論我是作者還是接收者,都無關緊要。我如何用Lodash實現這一目標?

我們來說說這個示例代碼。

const messages = [ 
    { id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } }, 
    { id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } }, 
    { id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } }, 
] 

想象一下,我的用戶ID = 1,所以我希望得到這樣的:

const chats = [ 
    { 
    chatName: 'Name of user ID 2', messages: [ 
     { id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } }, 
     { id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } }, 
    ] 
    }, 
    { 
    chatName: 'Name of user ID 3', messages: [ 
     { id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } }, 
    ] 
    } 
]; 

我如何與Lodash實現這一目標?

回答

1

不確定lodash,但你可以使用純JS - reducemap獲得該結構

const messages = [{ 
 
    id: '100', 
 
    text: 'aaa', 
 
    author: { 
 
     id: '1' 
 
    }, 
 
    receiver: { 
 
     id: '2' 
 
    } 
 
    }, 
 
    { 
 
    id: '101', 
 
    text: 'bbb', 
 
    author: { 
 
     id: '2' 
 
    }, 
 
    receiver: { 
 
     id: '1' 
 
    } 
 
    }, 
 
    { 
 
    id: '102', 
 
    text: 'ccc', 
 
    author: { 
 
     id: '3' 
 
    }, 
 
    receiver: { 
 
     id: '1' 
 
    } 
 
    }, 
 
]; 
 

 
function groupByPair(arr) { 
 
    return [ 
 
    ...arr.reduce((a, b) => { 
 
     let { 
 
     author, 
 
     receiver 
 
     } = b; 
 
     let s = [author.id, receiver.id].sort().join('-'); 
 
     a.set(s, a.has(s) ? a.get(s).concat(b) : [b]); 
 
     return a; 
 
    }, new Map) 
 
    ].map(e => ({ 
 
    chatName: 'Name of user ID ' + e[0].substring(e[0].indexOf('-') + 1), 
 
    messages: e[1] 
 
    })); 
 
} 
 
console.log(groupByPair(messages));

0

你可以用_.groupby做到這一點。我第一次篩選陣列,這樣你只涉及用戶的郵件,在1

const messages = [ 
 
    { id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } }, 
 
    { id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } }, 
 
    { id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } }, 
 
]; 
 

 
const filtered = messages.filter((msg) => { 
 
    return msg.author.id === '1' || msg.receiver.id === '1' 
 
}); 
 

 
const groups = _.groupBy(filtered, (msg) => { 
 
    return msg.author.id === '1' ? msg.receiver.id : msg.author.id 
 
}); 
 

 
console.log(groups);
<script src="https://unpkg.com/[email protected]"></script>

1

無論是使用Lodash或Underscore.js:

var grouped = _.groupBy(messages, m => _.sortBy([m.author.id, m.receiver.id])); 
var formatted = _.map(grouped, (v, name) => ({ chatname: name, messages: v })); 

你可以將這些組合成一條線,但這似乎對我的眼睛過於密集。

我拿了定義一個更復雜的測試數據集的自由,以確保邊緣情況較好覆蓋:

var messages = [ 
    { id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } }, 
    { id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } }, 
    { id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } }, 
    { id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } }, 
    { id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } }, 
    { id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } } 

]

有了這些數據,上面的代碼產生的formatted

[ 
    { chatname: '1,2', 
    messages: [ 
     { id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } }, 
     { id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } }, 
     { id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } } 
    ] 
    }, 
    { chatname: '1,3', messages: [ 
     { id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } }, 
     { id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } } 
    ] 
    }, 
    { chatname: '3,4', messages: [ 
     { id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } } 
    ] 
    } 
] 

與您期望的輸出的主要區別在於chatname值。我沒有看到你是如何命名這些的,所以我堅持使用Lodash/Underscore的原生groupby鍵。

相關問題