2

The original array has several objects within it, each of these objects has three properties (timestamp, name and age).

If multiple timestamps in a row are 15 minutes apart, they will be grouped into the same object. Afterwards, a new property called end will be added, which will be the timestamp value of the last element of this group plus 15 minutes.

If there are not several elements in a row with a difference of 15 minutes between them, the end property will have the timestamp plus 15 minutes as a value.

This is my current code:

const data = [
    {
        timestamp: '2021-11-23T14:15:00+0000',
        name: 'John',
        age: 25,
    },
    {
        timestamp: '2021-11-23T14:30:00+0000',
        name: 'John',
        age: 25,
    },
    {
        timestamp: '2021-11-23T14:45:00+0000',
        name: 'John',
        age: 25,
    },
    {
        timestamp: '2021-11-23T15:45:00+0000',
        name: 'John',
        age: 25,
    },
    {
        timestamp: '2021-11-23T14:15:00+0000',
        name: 'Anne',
        age: 32,
    },
    {
        timestamp: '2021-11-23T14:30:00+0000',
        name: 'Anne',
        age: 32,
    },
    {
        timestamp: '2021-11-23T14:45:00+0000',
        name: 'Anne',
        age: 32,
    },
    {
        timestamp: '2021-11-23T15:45:00+0000',
        name: 'Anne',
        age: 32,
    },
]

const newArray = data.reduce((accumulator, current) => {
    const end = new Date(Date.parse(current.timestamp) + 15 * 60 * 1000)
    if (accumulator.length === 0) {
        accumulator.push({
            ...current,
            end,
        })
    } else {
        const last = accumulator[accumulator.length - 1]
        if (last.name === current.name && last.age === current.age) {
            last.end = end
        } else {
            accumulator.push({
                ...current,
                end,
            })
        }
    }
    return accumulator
}, [])

console.log(newArray)

However the end result of my code is not exactly what I want. I would like my result to be like this:

[
    {
        timestamp: '2021-11-23T14:15:00+0000',
        name: 'John',
        age: 25,
        end: '2021-11-23T15:00:00+0000'
    },
    {
        timestamp: '2021-11-23T15:45:00+0000',
        name: 'John',
        age: 25,
        end: '2021-11-23T16:00:00+0000'
    },
    {
        timestamp: '2021-11-23T14:15:00+0000',
        name: 'Anne',
        age: 32,
        end: '2021-11-23T15:00:00+0000'
    },
    {
        timestamp: '2021-11-23T15:45:00+0000',
        name: 'Anne',
        age: 32,
        end: '2021-11-23T16:00:00+0000'
    }
]
4
  • Why does the output have half the number of objects than that of the input? Commented Nov 24, 2021 at 8:04
  • @ze00ne I did not understand the question. I would like to do this so it would be simpler for me to work with the data. Commented Nov 24, 2021 at 8:15
  • The end result has 4 objects {} and the original array has 8 objects {}...why? Commented Nov 24, 2021 at 8:24
  • Just a question, are you asking why I want to go from 8 objects to 4? @zer00ne Commented Nov 24, 2021 at 8:28

2 Answers 2

2

You could search for the last interval and update end if found. Otherwise add a new object.

const data = [{ timestamp: '2021-11-23T14:15:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:30:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:45:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T15:45:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:15:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T14:30:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T14:45:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T15:45:00+0000', name: 'Anne', age: 32 }]

const newArray = data.reduce((accumulator, current) => {
    const
        end = new Date(Date.parse(current.timestamp) + 15 * 60 * 1000).toISOString(),
        item = accumulator.find(o =>
            o.name === current.name &&
            o.end === new Date(current.timestamp).toISOString()
        );
    
    if (item) item.end = end;
    else accumulator.push({ ...current, end });

    return accumulator;
}, [])

console.log(newArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

1

You can use Array.reduce() to get the required result as in your own code, but we can make a slight change to update the lastItem in the accumulator array if

  • The names are the same (lastItem.name === name)
  • The dates are within 15 minutes

If this condition isn't met we simply add to the accumulator array.

const data = [ { timestamp: '2021-11-23T14:15:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:30:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:45:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T15:45:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:15:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T14:30:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T14:45:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T15:45:00+0000', name: 'Anne', age: 32, }, ] 
    
const result = data.reduce((acc, { timestamp, name, age }) => { 
    let lastItem = acc[acc.length - 1];
    let end = new Date(Date.parse(timestamp) + 15*60*1000);
    
    // If the current row matches just update the end time
    if (lastItem && lastItem.name === name && (Date.parse(lastItem.end) - Date.parse(timestamp) >= 0)) { 
        lastItem.end = end;
    } else {
        acc.push({ timestamp, name, age, end });
    } 
    return acc;
}, [])

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.