简体   繁体   中英

How to reduce a string into a custom object using several delimiters, Uncaught (in promise): TypeError: Cannot read property of undefined

I have a string that exists in the following format...

"6:00AM - Get up, Make the bed, Brush my teeth. 6:45AM - Take a shower. 7:15AM - Have breakfast, Leave for school."

I'd like to reduce that string based on the period, comma and dash. Basically get an object with time and activities. The object should look like this...

{
  6:00AM: ['Get up', 'Make the bed', 'Brush my teeth'],
  6:45AM: ['Take a shower'],
  7:15AM: ['Have breakfast', 'Leave for school']
}

How can I go about doing that? I can't quite figure it out.

The content below is what I've added.

Now, I have an object coming from the database that looks like this...

[
  {
    "id": 1,
    "day": "Monday",
    "activities": "6:00AM - Get up, Make the bed, Brush my teeth. 6:45AM - Take a shower. 7:15AM - Have breakfast, Leave for school."
  },
  {
    "id": 2,
    "day": "Tuesday",
    "activities": "6:00AM - Get up, Make the bed, Brush my teeth. 6:45AM - Take a shower. 7:15AM - Have breakfast, Leave for school."
  }
]

I'd like to loop over that array and replace the value of each activities property with the transformed string (ie the returned object). I have thus created a separate variable called activities and instantiated it to an array, where I wish to store the objects returned from transforming the activities property . So..

let activities = [];

/* My function */ 
private splitter() {
  const activities = this.itinerary.map(item => {
    return item.activities;
  });

  const results = {};
  const res = activities.map(str => {
    for (const result of str.split('.').map(x => x.trim())) {
      if (result) {
        const [time, actions] = result.split(' - ');
        results[time] = actions.split(',').map(x => x.trim());
      }
    }
    return results;
  });
  return res;
}

I hoped to achieve something that looks like this...

[
    {
      6:00AM: ['Get up', 'Make the bed', 'Brush my teeth'],
      6:45AM: ['Take a shower'],
      7:15AM: ['Have breakfast', 'Leave for school']
    },
    {
      6:00AM: ['Get up', 'Make the bed', 'Brush my teeth'],
      6:45AM: ['Take a shower'],
      7:15AM: ['Have breakfast', 'Leave for school']
    }
]

However, I get the error...

Uncaught (in promise): TypeError: Cannot create property '6:00AM' on string '6:00AM - Get up, Make the bed, Brush my teeth.'

How can I get this to work?

This will do the trick using nothing but built-in JavaScript that should run in any recent version of Node.JS:

const str = "6:00AM - Get up, Make the bed, Brush my teeth. 6:45AM - Take a shower. 7:15AM - Have breakfast, Leave for school."

sentences = {};
// split the string on periods, and trim each sentence
for (sentence of str.split('.').map(x => x.trim())) {
    // you end up with a completely empty sentence when the last
    // sentence ends in a period, which is uninteresting
    if (sentence) {
        // split each sentence on a hyphen, and assume the first
        // element is time and the second is actions
        let [time, actions] = sentence.split(' - ');

        // split the actions string on commas and trim whitespace;
        // store that in our sentences object
        sentences[time] = actions.split(',').map(x => x.trim());
    }
}

Then console.log(sentences) at the end gives you:

{ '6:00AM': [ 'Get up', 'Make the bed', 'Brush my teeth' ],
  '6:45AM': [ 'Take a shower' ],
  '7:15AM': [ 'Have breakfast', 'Leave for school' ] }

Maybe this is a pretty naive solution, but you can resolve something like this with a combination of split and map .

Lets say you have your string. You can start splitting it by the first biggest delimiter (the period in this example).

const string = "6:00AM - Get up, Make the bed, Brush my teeth. 6:45AM - Take a shower. 7:15AM - Have breakfast, Leave for school."
const firstSplit = string.split(".");

What you have now in firstSplit would be something like ["6:00AM - Get up, Make the bed, Brush my teeth", "6:45AM - Take a shower", "7:15AM - Have breakfast, Leave for school"] . What you can do now is to further split each one of the values in this array into hour and activites.

Since I want to split each item in the array (obtaining a new array with the results) I will use a map

const secondSplit = firstSplit.map(each => each.split(" - "))

Now secondSplit will look something like [["6:00AM", "Get up, Make the bed, Brush my teeth"], ["6:45AM", "Take a shower"], ["7:15AM", "Have breakfast, Leave for school"]]

Now lets transform that weird array of arrays into an object in which the first position of each small array is a key, and second a value. I will use vainilla javascript but of course this will be easier with any js library out there (like lodash or ramda)

const almostThere = secondSplit.reduce((object, subarray) => {
  object[subarray[0]] = subarray[1]
  return object
}, {})

This is incredible close to what you actually want. The object is looking something like:

{
  6:00AM: "Get up, Make the bed, Brush my teeth",
  6:45AM: "Take a shower",
  7:15AM: "Have breakfast, Leave for school"
}

Notice we are missing one more split on each of the object values. We can tackle that by modifying the reduce done previously

const yeay = secondSplit.reduce((object, subarray) => {
  object[subarray[0]] = subarray[1].split(", ")
}, {})

And there you go!

Altogether it might look something like this:

const firstSplit = string.split(".")
 .map(each => each.split(" - "))
 .reduce((object, subarray) => {
  object[subarray[0]] = subarray[1].split(", ")
  return object
}, {})

Which might be optimized to something like this:

const yeay = string.split(".")
 .reduce((object, hourAndChores) => {
    const splittedHourAndChores = hourAndChores.split(" - ");
    object[splittedHourAndChores[0]] = splittedHourAndChores[1].split(", ")
    return object
}, {})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM