1

I have these JSON:

var tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
};

Well, I want to access to the previous track, for example: I have "track2" and I want to store in a variable called previous, the location of "baby_be_mine".

I have this for and inside of it I have tried to do that with track-1, but the console got me undefined.

for(var track in tracks){
    if(track-1 >0){
        previous = tracks[track-1][2];
    }
apwnn
  • 87
  • 7
  • 1
    problem is it is not an index so you can't just subtract one. – epascarello Nov 19 '19 at 19:04
  • 2
    From the looks of it those track key/value pairs probably belong to an object, and object entries are not in guaranteed order. – Dexygen Nov 19 '19 at 19:07
  • @GeorgeJempty modern day browsers there is.... – epascarello Nov 19 '19 at 19:08
  • @epascarello George is right here see https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – Aditya Shankar Nov 19 '19 at 19:11
  • Add your complete JSON, as this is not valid. And could you structure it differently? There are better data structures for what you want to achieve. – ssc-hrep3 Nov 19 '19 at 19:12
  • @epascarello Plenty of applications still need to support IE11 and earlier -- the one I'm currently working on does, as did one I was working on a couple of years ago. – Dexygen Nov 19 '19 at 19:12
  • 1
    @GeorgeJempty I'm sorry I made a correction to my question. I saved the JSON into an object. – apwnn Nov 19 '19 at 19:14

6 Answers6

1

An example on how to do it with your data structure:

const tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
};

const trackKeys = Object.keys(tracks).sort();
for (let i = 0; i < trackKeys.length; i++) {
  let currentTrackKey = trackKeys[i];
  if (i === 0) {
    console.log('previousTrack of ' + currentTrackKey + ' is:', undefined);
  } else {
    let previousTrackKey = trackKeys[i - 1];
    console.log('previousTrack of ' + currentTrackKey + ' is:', tracks[previousTrackKey]);
  }
}

Using a better data structure in your JSON:

It would be much better to use a data structure which does not contain a key with an index in it as a string. It's also not advised to use arrays with items with different meaning which you then access by index. Use an object for that. Here is an example:

const tracks = [{
  title: 'Baby Be Mine',
  interpret: 'Michael Jackson',
  key: 'baby_be_mine'
}, {
  title: 'Thriller',
  interpret: 'Michael Jackson',
  key: 'thriller'
}, {
  title: 'Humane Nature',
  interpret: 'Michael Jackson',
  key: 'humane_nature'
}];

for (let i = 0; i < tracks.length; i++) {
  let currentTrack = tracks[i];
  if (i === 0) {
    console.log('previousTrack of ' + currentTrack.key + ' is:', undefined);
  } else {
    let previousTrack = tracks[i - 1];
    console.log('previousTrack of ' + currentTrack.key + ' is:', JSON.stringify(previousTrack));
  }
}

Benefits of a better data structure

With a data structure like in the 2nd example, you could also e.g. very easily filter by e.g. interpret, map to a list of all interprets etc.

const tracks = [{
  title: 'Baby Be Mine',
  interpret: 'Michael Jackson',
  key: 'baby_be_mine'
}, {
  title: 'Thriller',
  interpret: 'Michael Jackson',
  key: 'thriller'
}, {
  title: 'Humane Nature',
  interpret: 'Michael Jackson',
  key: 'humane_nature'
}];

console.log('Tracks including "Baby" in the title:', tracks.filter(track => track.title.includes('Baby')));
console.log('List of interprets:', tracks.map(track => track.interpret));
console.log('Number of tracks by Michael Jackson:', tracks.filter(track => track.interpret === 'Michael Jackson').length);
ssc-hrep3
  • 15,024
  • 7
  • 48
  • 87
0

Object here seems like it is actually the wrong format for your data. An array would be better. Since you are not using an array, your problem is you are not there is no way to look back an index. Since you are looping you can store it in a variable and update it on each iteration

const tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
}

let prevTrack = null
for (let track in tracks) {
  console.log(track, prevTrack)
  prevTrack = track
}

Other option would be to convert it into an array with object.values

const tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
}

const listing = Object.values(tracks)
listing.forEach( function (current, index, arr) {
  let prev = arr[index-1] || null
  console.log(current[2], prev ? prev[2] : 'N/A')
})
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

Here is one...:

const tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
};

let previous = "";
const trackNumbers = Object.keys(tracks);
for (let i = 0; i < trackNumbers.length; i++) {
    let previousIndex = i - 1;
    if ( previousIndex > 0) {
        previous = tracks[trackNumbers[previousIndex]][2];
        console.log(previous);
    }
}
Cuong Nguyen
  • 314
  • 2
  • 8
0

Thats because track is a string,

to check this out do

also, @George Jempty in the comments is right, JS does not guarantee insertion order,see Does JavaScript Guarantee Object Property Order?

thus rewrite tracks to be an array

i.e. convert

var tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
};

to

var tracks = [
    ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    ['Thriller', 'Michael Jackson', 'thriller'],
    ['Humane Nature', 'Michael Jackson', 'humane_nature']
];

arrays DO guarantee insertion order,

so, now do,

for(var i=0; i<tracks.length; i++){
    if(i-1 >0){
        previous = tracks[i-1][2];
        ...
    }
}

Issue #2 With the original var tracks = {...}, when you accessed it via

for(var track in tracks){
    if(track-1 >0){
        previous = tracks[track-1][2];
    }
}

here track is a String, not a number, so (track - 1) makes no sense and gives NaN

you can see this using Console.log(track)

Aditya Shankar
  • 702
  • 6
  • 12
0

var tracks = {
    "track1": ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    "track2": ['Thriller', 'Michael Jackson', 'thriller'],
    "track3": ['Humane Nature', 'Michael Jackson', 'humane_nature']
};

function getPrevTrackTo(trackName) {
    var trackNames = Object.keys(tracks).sort();
    var currentTrackIndex = trackNames.indexOf(trackName);
    var prevTrackName = currentTrackIndex < 1 ? null : trackNames[currentTrackIndex - 1];
    return prevTrackName === null ? null : tracks[prevTrackName];
}

var prevTrack = getPrevTrackTo('track2');

console.log(prevTrack)
Vadim Loboda
  • 2,431
  • 27
  • 44
0

As comments suggested, maybe you should't keep it in Json but array?

var tracks = [
    ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine'],
    ['Thriller', 'Michael Jackson', 'thriller'],
    ['Humane Nature', 'Michael Jackson', 'humane_nature']
];

Or just create an array from your object. If track1, track2, track3 are meaningful key values that you might wanna use it later. Then pass them into your array items :

objectArray = Object.entries(tracks).map(([key, value]) => ({key,value}))

objectArray will be :

[
  {key: "track1", value: ['Baby Be Mine', 'Michael Jackson', 'baby_be_mine']},
  {key: "track2", value: ['Thriller', 'Michael Jackson', 'thriller']},
  {key: "track3", value: ['Humane Nature', 'Michael Jackson', 'humane_nature']},
]

Then simply :

for(var track in objectArray){
    if(track-1 >0){
        previous = objectArray[track-1].value[2];
    }
}
Kerem atam
  • 2,387
  • 22
  • 34