Home > Software engineering >  Javascript: How to reduce json when consecutive key is the same?
Javascript: How to reduce json when consecutive key is the same?

Time:01-19

I have a json where I need to reduce the items when they are of a type (isSender).
I need to reduce them when they are occurring consecutively.
The data can change.

The data looks like this:

 "messages": [
    { "content": ["Foo"], "isSender": true },
    { "content": ["Bar"], "isSender": true },
    { "content": ["Lorem"], "isSender": true },
    { "content": ["Ipsum"], "isSender": true },
    { "content": ["Dolor"], "isSender": false },
    { "content": ["Sit Amet"], "isSender": false },
    { "content": ["No"], "isSender": true }
  ]

I need the content to be an array of messages when the consecutive isSender key is the same. The output should look like this:

  "messages": [
    {
      "content": ["Foo", "Bar", "Lorem", "Ipsum"],
      "isSender": true
    },
    { "content": ["Dolor", "Sit amet"], "isSender": false },
    { "content": ["No"], "isSender": true }
  ]

So far I have tried looping through the message array and checking if next messages have the same isSender key. However this does not work for more than 2 messages.

let deleteIndex = [];
 for(let i = 0  ; i < messages.length - 1; i  ) {
        const currMs = messages[i];
        const nextMs = messages[i   1];
        if (nextMs.isSender == currMs.isSender) {
            currMs.content.push(nextMs)
            deleteIndex.push(i   1) // saving index to be deleted once for loop is done
        }
    }

Can someone give me a clue on how to work around this?

Thanks in advance.

CodePudding user response:

Use reduce(), on each iteration, we check if the last element in the result array has the same isSender value as the current object we're dealing with.

if (p.length && p.at(-1).isSender === c.isSender) {

So, if we already have something in the final array (p.length) AND the last isSender (p.at(-1).isSender) has the same value as the current isSender (c.isSender), append to that content list

Otherwise, add the entry, which is just the current object itself (return [ ...p, c ])

const data =  [
    { "content": ["Foo"], "isSender": true },
    { "content": ["Bar"], "isSender": true },
    { "content": ["Lorem"], "isSender": true },
    { "content": ["Ipsum"], "isSender": true },
    { "content": ["Dolor"], "isSender": false },
    { "content": ["Sit Amet"], "isSender": false },
    { "content": ["No"], "isSender": true }
  ];
  
const res = data.reduce((p, c) => {
    if (p.length && p.at(-1).isSender === c.isSender) {
        p.at(-1).content.push(...c.content);
        return p;
    }
    return [ ...p, c ];
}, [])

console.log(res);

[
  {
    "content": ["Foo", "Bar", "Lorem", "Ipsum"],
    "isSender": true
  },
  {
    "content": ["Dolor", "Sit Amet"],
    "isSender": false
  },
  {
    "content": ["No"],
    "isSender": true
  }
]

CodePudding user response:

you can try this

    JArray jArr = JObject.Parse(json)["messages"] as JArray;

    var noContent = jArr.Select(a => a)
                        .Where(a => string.Join(",", a["content"]) == "No")
                        .FirstOrDefault();

    jArr.Remove(noContent);

    var jObj = new JObject
    {
        ["messages"] = new JArray(jArr.GroupBy(x => x["isSender"])
                       .Select(g => new JObject
                       {
                           ["content"] = new JArray(g.SelectMany(y => y["content"])),
                           ["isSender"] = g.Key
                       }))
    };
    
    ((JArray)jObj["messages"]).Add(noContent);

    json = jObj.ToString();
    
    //or if you create a  Messages class
    
    Messages messages = jObj.ToObject<Messages>();

json output

{
  "messages": [
    {
      "content": [
        "Foo",
        "Bar",
        "Lorem",
        "Ipsum"
      ],
      "isSender": true
    },
    {
      "content": [
        "Dolor",
        "Sit Amet"
      ],
      "isSender": false
    },
    {
      "content": [
        "No"
      ],
      "isSender": true
    }
  ]
}
  • Related