使用Lodash反转键值

问题描述

鉴于我有以下对象

{
    "a": ["100","200"],"b": ["100"],"c": ["100","200","300"],"d": ["200"]
}

如何反转它,而不是成为值列表的键,而是对应键列表的值,就像这样:

{
    "100": ["a","b","c"],"200": ["a","c","d"],"300": ["c"]
}

我尝试过_.reverse,但实际上只是反转了键和值。

解决方法

使用Array.prototype.reduce通过值缩小当前对象,并检查缩小的键数组中是否存在该键,如果不存在则添加它。

const obj = {
    "a": ["100","200"],"b": ["100"],"c": ["100","200","300"],"d": ["200"]
};

const groupedResult = Object.entries(obj)
.reduce((r,[key,val]) => {
    val.forEach((item) => {
        if (!r[item]) {
            r[item] = [key];
        } else {
            if (!r[item].includes(key)) {
                r[item].push(key);
            }
        }
    });
    
    return r;
},Object.create(null));

console.log(groupedResult);

,

您可以使用 import React from 'react' import io from 'socket.io-client' import Peer from 'peerjs' import './ClassWall.css' import { Modal,Button } from 'antd'; import img from '../../uploads/349-3498013_laptop-personal-computer-diagram-computer-icons-download-laptop-clipart.png' const socket = io.connect('http://localhost:4000/') class LiveClass extends React.Component{ constructor(){ super() this.state = { userId :'',classStatus: '',videoSrc:'',visible: false } } async componentDidMount(){ //set the user id of logedin user const videoGrid = document.getElementById('video-grid') const Myvideo = document.createElement('video') Myvideo.addEventListener('click',()=>{ console.log(Myvideo) }) Myvideo.muted = true try { const response = await fetch('http://localhost:4000/Auth//UserID/id',{ headers:{token:localStorage.token} }) const Parse = await response.json() this.setState({userId:Parse}) } catch (error) { } //get user id to connect through peer const myPeer = new Peer(this.state.userId,{ host: '/',port:4001 }) //connect and share video stream try { const peers = {} navigator.mediaDevices.getUserMedia({ video:true,audio:true }).then(stream =>{ addVideoStream(Myvideo,stream) myPeer.on('call',call=>{ call.answer(stream) const video = document.createElement('video') call.on('stream',userVideostream=>{ addVideoStream(video,userVideostream) }) }) socket.on('user-connected',userId=>{ connectToNewUser(userId,stream) console.log('newUser',userId) }) }) socket.on('user-disconnect',userId=>{ if(peers[userId])peers[userId].close() }) myPeer.on('open',id=>{ socket.emit('join-class',this.props.match.params.id,id) }) //get user stream and connect function connectToNewUser(userId,stream){ const call = myPeer.call(userId,stream) const video = document.createElement('video') video.setAttribute("class",`pointer`) video.addEventListener('click',()=>{ console.log(video) }) call.on('stream',userVideostream) }) call.on('close',()=>{ video.remove() }) peers[userId]=call } //Add video stream function addVideoStream(video,stream){ const videoGrid = document.getElementById('video-grid') video.srcObject = stream video.addEventListener('loadedmetadata',() =>{ video.play() }) videoGrid.append(video) } } catch (error) { console.log('error',error) } this.checkIfClassTrue() } //check if its class checkIfClassTrue = async()=>{ const response = await fetch(`http://localhost:4000/liveclass/${this.props.match.params.id}`) const Parse = await response.json() this.setState({classStatus:Parse}) } //modal showModal = () => { this.setState({ visible: true,}); }; handleOk = e => { console.log(e); this.setState({ visible: false,}); }; handleCancel = e => { console.log(e); this.setState({ visible: false,}); }; render(){ return( <div> { this.state.classStatus === 'Not found'? 'not found': <div> <div id="video-grid"> {/* <img src={img}/> */} </div> <Button type="primary" onClick={this.showModal}> Open Modal </Button> <Modal title="Basic Modal" visible={this.state.visible} onOk={this.handleOk} onCancel={this.handleCancel} > </Modal> </div> } </div> ) } } export default LiveClass _.reduce()

_.forEach()
const data = {
  a: ["100",b: ["100"],c: ["100",d: ["200"],}

const res = _.chain(data)
  .reduce((result,value = [],key) => {
    _.forEach(value,(v) => {
      result[v] = [...(result[v] || []),key]
    })
    return result
  },{})
  .value()

console.log(JSON.stringify(res,null,2))

,

好吧,您可以向后减少它,以创建哈希作为结果,并保持更新。如果您在地图中找到该键(即您的值),请在地图中获取该键的值并添加当前键,否则创建一个空数组并添加当前键。

这是一个带有lodash的代码段(在lidash中,您可以直接在对象上应用_.reduce

let obj = {
    "a": ["100","d": ["200"]
};

let res = _.reduce(obj,(r,e,k) => e.reduce((_,n) => (r[n] = (r[n] || [])).push(k) && r,r),{});

console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

好吧,现在我在这里使用了lodash,所以我可以直接在对象上应用reduce,否则您可以将其转换(对象输入)为条目,并在条目上应用普通JS reduce。因此,第一个reduce之前的代码将在此处稍作更改,请参见下面没有lodash的纯JS版本:

let obj = {
    "a": ["100","d": ["200"]
};

let res = Object.entries(obj).reduce((r,[k,e]) => e.reduce((_,{});

console.log(res);