简体   繁体   中英

Turning this string into an object

I have this string (which is called data)

||id: ticket/327364|Subject: TestSubject|Due: 2018||--||id: ticket/327366|Subject: TestTwo|Due: 2018|||

That I want to turn into an object that is accessible using key/values. Step 1 is splitting the string on "--" and removing all the "|" signs. Which I did like this

var dataArray = [];
data.split("--").forEach(function(x) {
    var arr = x.split("|");
    arr = arr.filter(function(e) {
        return e;
    });
    dataArray.push(arr);
});

This gives me a multidimensional array

[Array(3), Array(3)]
    0: ["id: ticket/327364", "Subject: Beställning av inkoppling", "Due: Ej inställd"]
    1: ["id: ticket/327366", "Subject: Beställning av inkoppling", "Due: Ej inställd"]

And this is where I am stuck, because I want to split each of these arrays on ":". So Object.Due will give me the due-date and Object.Subject gives me the Subject etc. Also, it's not always going to be id, Subject, and Due. Sometimes it might be less or more entries.

I have tried this

var result = {};
dataArray.forEach(function(x) {
    x.forEach(function(y) {
       var newArr = y.split(":");
       newArr[1] && (result[newArr[0]] = newArr[1]);
    });
});

Which gives me exactly what I want, it gives me an object like this.

{id: " ticket/327366", Subject: " TestTwo", Due: " 2018"}

However, result only contains the data from the last array. It's like it overwrites the first one. Any suggestions on how to re-do this? Also, it feels like an awful lot of loops but I've only been dabbling with JS for a day or two so I haven't really figured out a different way of doing it.

In the second code block you are building only one object: you want an array, yet result is not an array. Move that object declaration inside the outer loop, and push that object to the final array at the end of each iteration. See the comments in your code where I made changes:

 var data = '||id: ticket/327364|Subject: TestSubject|Due: 2018||--||id: ticket/327366|Subject: TestTwo|Due: 2018|||'; var dataArray = []; data.split("--").forEach(function(x) { var arr = x.split("|"); arr = arr.filter(function(e) { return e; }); dataArray.push(arr); }); var resultArray = []; // <--- final array dataArray.forEach(function(x) { var result = {}; // <--- one object per iteration x.forEach(function(y) { var newArr = y.split(":"); newArr[1] && (result[newArr[0]] = newArr[1]); }); resultArray.push(result); // <--- push it }); console.log(resultArray); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Alternative, functional programming way

Here is an alternative way, which uses several ES6 features such as spread syntax, arrow functions, Object.assign and computed property syntax:

 const data = '||id: ticket/327364|Subject: TestSubject|Due: 2018||--||id: ticket/327366|Subject: TestTwo|Due: 2018|||'; const dataArray = data.split("--").map(x => Object.assign(... x.split("|") .filter(e => e) .map(s => s.split(':')) .map(([key, value]) => ({ [key]: value.trim() })) ) ); console.log(dataArray); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Well, that's because, as I understand, you are creating a single object each time in the result variable, so you are overwriting the result at each time in the loop. I think you sould insert the result object in an Array of results and iterate through it inserting in every cicle of the loop the result in the array with .push().

Don't know if that make sense for you.

Here's a different approach that avoids unwanted referencing:

 const input = '||id: ticket/327364|Subject: TestSubject|Due: 2018||--||id: ticket/327366|Subject: TestTwo|Due: 2018|||'; const result = input .split('--') .map(subArray => { const resultObject = {}; const filtered = subArray .split('|') .filter(item => item.length > 0); for (let element of filtered) { const [key, value] = element.split(':'); resultObject[key] = value.trim(); } return resultObject; }); console.log(result); 

In your version, you are setting the value of the respective key to the new value, since the objects have repeated keys, they are being overwritten by the latest.

You want one result per dataArray entry, not one overall. So put the object creation it in the right place, and collect them in an array:

var results = dataArray.map(function(x) {
    var result = {};
    for (var y of x) {
       var newArr = y.split(":");
       if (newArr[1]) result[newArr[0]] = newArr[1];
    }
    return result;
});

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