【问题标题】:In an array, display an object only once if it has the same id, but still display other properties在数组中,如果对象具有相同的 id,则仅显示一次,但仍显示其他属性
【发布时间】:2020-09-29 14:42:42
【问题描述】:

我想要实现的是我想一个一个地显示fromUsers,但没有重复。因此,如果我有 2 条来自同一个 John(同一个 fromUserId)的消息,那么我希望这个 John 的名字只出现一次,因为它是同一个 John 和同一个 fromUserId。然后,一旦我点击 John 的名字,我就会看到 2 条消息(hi + hey)。我们无法摆脱任何对象,因为message 不同,我仍然需要显示这些消息。有可能实现这一点吗?我正在使用 Node.js、Mongodb、Mongoose 和 React。

[
    {
        "message": "hi",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
    },
    {
        "message": "hey",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
    },
    {
        "message": "ola",
        "fromUser": "Jane",
        "fromUserId": "5ed9d49c7e516616600eb693",
    }
]

渲染:

            <div>
                {this.state.from.map((from) => {
                    return <div key={from._id}>{from.fromUser}</div>;
                })}
            </div>

axios 获取请求:

            axios.get('/api/getMessage', { headers: { 'X-Auth-Token': token } }).then((res) => {
                this.setState({ from: res.data });
            });

类组件中的状态:

    this.state = {
        message: '',
        from: [],
    };

【问题讨论】:

  • 删除整个数据集中的重复项,还是仅在连续运行中?你能澄清预期的结果吗? IE。全局分组[[john, john, john], [jane, jane]] 或按顺序分组[[john, john], jane, john, jane]
  • [[john, john, john], [jane, jane]] 是正确的,但是 [[john, message, message]], [jane, message] 应该更理想,因为如果相同john 发送了很多消息,然后我不需要他的名字(同一个 John)不止一次,但我需要来自 john 等的每条消息。:)

标签: javascript node.js reactjs mongodb mongoose


【解决方案1】:

你应该使用reducer,把这段代码改成你的:

const arr = [
  { id: 1, name: "test1", msg: 'hi1' },
  { id: 2, name: "test2", msg: 'hi2' },
  { id: 2, name: "test3", msg: 'hi3' },
  { id: 3, name: "test4", msg: 'hi4' },
  { id: 4, name: "test5", msg: 'hi5' },
  { id: 5, name: "test6", msg: 'hi6' },
  { id: 5, name: "test7", msg: 'hi7' },
  { id: 6, name: "test8", msg: 'hi8' }
];

const filteredArr = arr.reduce((acc, current) => {
  const x = acc.find(item => item.id === current.id);
  if (!x) {
    return [...acc, current];
  } else {
    return acc.map(x=> x.id === current.id ? ({...x, msg: x.msg + current.msg }) : x)
  }
}, []);

console.log(filteredArr)

结果:

[{
  id: 1,
  msg: "hi1",
  name: "test1"
}, {
  id: 2,
  msg: "hi2hi3",
  name: "test2"
}, {
  id: 3,
  msg: "hi4",
  name: "test4"
}, {
  id: 4,
  msg: "hi5",
  name: "test5"
}, {
  id: 5,
  msg: "hi6hi7",
  name: "test6"
}, {
  id: 6,
  msg: "hi8",
  name: "test8"
}]

【讨论】:

    【解决方案2】:

    我已将来自用户的所有消息包含在 users 对象内的数组 messages 中。

    let users = [{
        "message": "hi",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
      },
      {
        "message": "hey",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
      },
      {
        "message": "ola",
        "fromUser": "Jane",
        "fromUserId": "5ed9d49c7e516616600eb693",
      },
      {
        "message": "hi",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
      },
    ]
    
    let flags = [],
      output = [];
    users.forEach(user => {
      if (flags[user.fromUserId]) {
        output.forEach(item => {
          if (item.fromUserId === user.fromUserId) {
            item.messages = [...item.messages, user.message]
          }
        })
      } else {
        user.messages = [user.message]
        flags[user.fromUserId] = true;
        output.push(user);
      }
    })
    

    输出将如下所示:

    output = [{
        "message": "hi",
        "fromUser": "John",
        "fromUserId": "5edb1f10b82175355479f05a",
        "messages": ["hi", "hey", "hi"]
      },
      {
        "message": "ola",
        "fromUser": "Jane",
        "fromUserId": "5ed9d49c7e516616600eb693",
        "messages": ["ola"]
      }
    ]
    

    【讨论】:

      【解决方案3】:

      在给定的约束条件下,我会假设消息是有序的。另外,如果不是,请考虑添加时间戳。

      向前看,这个 json 可以显示为:

      John: hi
      John: hey
      
      Jane: ola
      

      但你要的是:

      John: hi hey
      Jane: ola
      

      以下代码将有助于将相似用户合并在一起:

      const chats = [
        {
          "message": "hi",
          "fromUser": "John",
          "fromUserId": "5edb1f10b82175355479f05a",
        },
        {
          "message": "hey",
          "fromUser": "John",
          "fromUserId": "5edb1f10b82175355479f05a",
        },
        {
          "message": "ola",
          "fromUser": "Jane",
          "fromUserId": "5ed9d49c7e516616600eb693",
        }
      ];
      
      userChat = {};
      // grouping the chat together
      for (const msg of chats) {
        let user = msg.fromUserId;
        if (userChat[user] === undefined) {
          userChat[user] = msg;
        } else {
          userChat[user].message += " " + msg.message;
        }
      }
      
      // printing the msg out
      for (const user in userChat) {
        console.log("User: ", userChat[user].fromUser);
        console.log("Message: ", userChat[user].message);
      }

      我特意选择了这种方式,以便它也可以扩展为多种用途。 (以防万一)

      【讨论】:

        【解决方案4】:

        使用对象映射将消息收集到数组中。结果数据格式为:
        [ { _id, fromUser, messages} ... ]

        const fromCollectMessages = from =>
          Object.values(from.reduce((chats,{message:m, fromUserId: _id, fromUser})=>{
            chats[_id] = chats[_id] || { _id, fromUser }
            chats[_id].messages = chats[_id].messages || []
            chats[_id].messages.push(m)
            return chats
          },{}))
        
        const data=[
            {
                "message": "hi",
                "fromUser": "John",
                "fromUserId": "5edb1f10b82175355479f05a",
            },
            {
                "message": "hey",
                "fromUser": "John",
                "fromUserId": "5edb1f10b82175355479f05a",
            },
            {
                "message": "ola2",
                "fromUser": "Jane",
                "fromUserId": "5ed9d49c7e516616600eb693",
            },
            {
                "message": "hi2",
                "fromUser": "John",
                "fromUserId": "5edb1f10b82175355479f05a",
            },
            {
                "message": "ola",
                "fromUser": "Jane",
                "fromUserId": "5ed9d49c7e516616600eb693",
            }
        ]
        
        console.log(fromCollectMessages(data))
        
        const { Component } = React,
              { render } = ReactDOM,
              el = document.getElementById('app')
              
        class Name extends Component {
          constructor(props) {
            super(props)
            this.state = {from: fromCollectMessages(props.from)}
          }
          render() {
            return (
              <div>
                  {this.state.from.map((from) => {
                      return <div key={from._id} style={{cursor:'pointer'}}
                        onClick={()=>alert(from.messages.join('\n'))}>
                          {from.fromUser}
                      </div>;
                  })}
              </div>
            )
          }
        }
        
        render(<Name from={data}/>,el)
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
        
        <div id="app"></div>

        【讨论】:

          【解决方案5】:

          简答:

          let output = input.reduce( (acc, cur) => {
              if(acc.map(item => item.fromUserId).includes(cur.fromUserId)){ //Check if the user is already included in the combined output
                  let found  = acc.find(entry => entry.fromUserId === cur.fromUserId); //If found, combine the messages       
                  found.message.push(cur.message);        
                  return acc;
              } else {
                  cur.message = [cur.message];    //the user is not included in the output yet   
                  acc.push(cur);                  //so add it to the output
                  return acc;
              }
          }, []);
          

          完整答案(可运行代码):

          let input = [
              {
                  "message": "hi",
                  "fromUser": "John",
                  "fromUserId": "5edb1f10b82175355479f05a",
              },
              {
                  "message": "hey",
                  "fromUser": "John",
                  "fromUserId": "5edb1f10b82175355479f05a",
              },
              {
                  "message": "ola",
                  "fromUser": "Jane",
                  "fromUserId": "5ed9d49c7e516616600eb693",
              }
          ];
          
          
          let output = input.reduce( (acc, cur) => {
              if(acc.map(item => item.fromUserId).includes(cur.fromUserId)){
                  let found  = acc.find(entry => entry.fromUserId === cur.fromUserId);        
                  found.message.push(cur.message);        
                  return acc;
              } else {
                  cur.message = [cur.message];
                  acc.push(cur);
                  return acc;
              }
          }, []);
          console.log(output);

          【讨论】:

            猜你喜欢
            • 2015-02-16
            • 1970-01-01
            • 2014-02-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-19
            • 2018-09-09
            相关资源
            最近更新 更多