converting a JSON array into an object

I seem to be facing a challenge:

I have a JSON list with rows of data and a JSON object. My goal is to iterate through the list and assign the rows to different objects within the JSON structure.

The first and last elements in the list are empty, followed by names and an indefinite number of "date" and "vote" pairs (refer to pastebin for clarity).

My objective is to aggregate all the votes under a specific name from the list into that particular JSON object.

How can I achieve this using JavaScript? Do I need to modify the JSON structure?

This is the initial JSON structure:

{
    "subjects": [
        {
            "electrical_and_electronic_engineering": {
                "grades": []
            }
        },

        {
            "italian_language_and_literature": {
                "grades": []
            }
        },

        {
            "english_language": {
                "grades": []
            }
        },

        {
            "mathematics_and_mathematical_complements": {
                "grades": []
            }
        },

        {
            "motor_and_sports_sciences": {
                "grades": []
            }
        },

        {
            "automatic_systems": {
                "grades": []
            }
        },

        {
            "history": {
                "grades": []
            }
        },

        {
            "technologies_and_design_of_electric_and_electronic_systems": {
                "grades": []
            }
        }
]
}

And here's the corresponding array:

[ '',
  'electrical and electronic engineering',
  '10',
  '7½',
  '8½',
  '5',
  '9',
  '7',
  '4',
  '7-',
  '7+',
  '6',
  '7½',
  'italian language and literature',
  '6½',
  '5+',
  '6',
  '7+',
  '5',
  '6½',
  'english language',
  '6+',
  '7',
  '7-',
  '7½',
  '7',
  '7+',
  'mathematics and mathematical complements',
  '4½',
  '9½',
  '7',
  '6½',
  '9',
  '7½',
  '4',
  '9',
  '7½',
  '7',
  '8',
  '8',
  'motor and sports sciences',
  '5',
  '7',
  '6',
  '9',
  '7',
  '10',
  '8',
  '10',
  '7',
  'automatic systems',
  '8',
  '8½',
  '10',
  '10',
  '8½',
  '9½',
  '10',
  '10',
  '10',
  '9-',
  'history',
  '4',
  '6',
  '5½',
  'technologies and design of electric and electronic systems',
  's',
  '7-',
  '7',
  '8',
  '8-',
  '7+',
  '7½',
  '6',
  '6',
  '8',
  '6+',
  '7-',
  '7-',
  '6',
  '7',
  '6',
  '8½',
  '' ]

Answer №1

Your array is a bit complex to work with. Here is a workaround to achieve what you are looking for. Keep in mind that a materia needs to be more than 2 characters long and the vote should be less than 3 characters, otherwise, it may not function correctly.

var array = [ '',
  'elettrotecnica ed elettronica',
  '10',
  '7½',
  '8½',
  '5',
  '9',
  '7',
  '4',
  '7-',
  '7+',
  '6',
  '7½',
  'lingua e letteratura italiana',
  '6½',
  '5+',
  '6',
  '7+',
  '5',
  '6½',
  'lingua inglese',
  '6+',
  '7',
  '7-',
  '7½',
  '7',
  '7+',
  'matematica e complementi di matematica',
  '4½',
  '9½',
  '7',
  '6½',
  '9',
  '7½',
  '4',
  '9',
  '7½',
  '7',
  '8',
  '8',
  'scienze motorie e sportive',
  '5',
  '7',
  '6',
  '9',
  '7',
  '10',
  '8',
  '10',
  '7',
  'sistemi automatici',
  '8',
  '8½',
  '10',
  '10',
  '8½',
  '9½',
  '10',
  '10',
  '10',
  '9-',
  'storia',
  '4',
  '6',
  '5½',
  'tecnologie e progettazione di sistemi elettrici ed elettronici',
  's',
  '7-',
  '7',
  '8',
  '8-',
  '7+',
  '7½',
  '6',
  '6',
  '8',
  '6+',
  '7-',
  '7-',
  '6',
  '7',
  '6',
  '8½',
  '' ];

var jsonObj = {'materie':[]}
var i = -1;
var currentKey = '';
array.map(function(val){
  if (val.length > 0) {
    if (val.length > 2) {
      currentKey = val.replace(/\s/g,'_');
      var newObj = {};
      newObj[currentKey] = {voti:[]}
      jsonObj['materie'].push(newObj);
      i++;
    } else {
      jsonObj['materie'][i][currentKey]['voti'].push(val);
    }
  }
});

document.write(JSON.stringify(jsonObj));

Answer №2

If my understanding is correct, you simply wish to extract names and votes from an array and insert them into a JavaScript object (JSON object). One approach to achieve this is by iterating over the array and checking if the format is consistent with name+date,vote. If the first item in the array is a character, it signifies a name. Then, you can locate the corresponding object in the JSON array and proceed to iterate through all values until another character item is encountered. Below is a quick solution, which may need adjustments for proper loop functionality:

//function to check for numbers
function isNumber(n) {
   return !isNaN(parseFloat(n)) && isFinite(n);
}   
function isEmpty(str) {
   return (!str || str.length === 0);
}
var jsonObject //the object we're appending the values to in your example
var name
var i = 1 //skipping the first empty value
for( i < voteArray.length() ){
  //check if a number 
  if (!isNumber(voteArray[i].charAt(0)) )
    if ( isEmpty(voteArray[i])){
      //end of list, break.
      break;
    }
    name = voteArray[i];
    //parse next two values and validate if they are numbers
    for( i < voteArray.length()){
        if(isNumber(voteArray[i+1]) && isNumber(voteArray[i+2])){
            //add the next numbers to JSON

            jsonObject[name].votes = //calculate total votes
            jsonOBject[name].date = //append date
            i=i+2 //increment i
        }
        else{
          if(isNumber(voteArray[i]){
            i = i+1;
            break;
          }else (isNumber(voteArray[i]){
            i = i+2;
            break;
          }
        }
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering the error "undefined object" while using the yield keyword in JavaScript

var pi = document.getElementById("pi"); function * calculatePi(){ let q = 1; let r = 0; let t = 1; let k = 1; let n = 3; let l = 3; while (true){ if (4*q+r-t < n*t){ alert(n); yield n; ...

Update the array state based on the selection of checkboxes and user input in real-time

In my current project using react js, I am working on a UI development task where I need to create a dynamic table based on data fetched from an API. Each row in the table includes a checkbox and a text input field that are dynamically generated. My goal i ...

Angular directive ng-template serves as a component type

In the code snippet below, <!DOCTYPE html> <html> <head> ..... </head> <body ng-app="app"> <script type="text/ng-template" id="my-info-msg.html"> <s ...

Unique Fragments with AstroJS

Recently delving into learning AstroJS, I stumbled upon some intriguing templates on GitHub. One thing that caught my attention was the <Fragment> tag which seemed to be related to directives based on the astro documentation. Below is a snippet of th ...

Automatic button rotation

I managed to set up a button that works on click with a delay, making it semi-automatic. However, I'm struggling with getting it to not pause after just one click. Here's what I have so far: <!DOCTYPE html> <html> <body> &l ...

Is there a way to eliminate empty arrays from my data?

I'm dealing with this PHP code snippet. public function display_children($parent,$level){ try { $cmd = $this->connection->prepare('SELECT mem,pid from mytree where pid = ?'); $cmd->execute(array($parent)); ...

Define the width of jqgrid

I have been utilizing SmartAdmin jqgrid to showcase data in tabular format. The number of columns in the datatable changes dynamically each time. I am converting the DataTable to a JSON object and assigning it to the jqgrid. However, it appears that jqgrid ...

Creating a dual-field autocomplete feature with jQuery and JSON data

I've been experimenting with jQuery's autocomplete widget and have hit a bit of a snag. I could really use some advice or guidance. Basically, I'm working on a form where users can input the name of a person, and then jQuery will search the ...

Guidelines for executing a Vue directive when the page is initially loaded

I am iterating through an array of objects containing map svg paths and locales, and I want to execute a function on load. The function needs to take the locale keys from the paths array as a parameter and perform some operation: <p v-for="(country ...

Preventing jQuery plugin from overriding default settings

I have created a jQuery plugin using the nested namespace pattern, inspired by the design template found in Addy Osmani's book. The plugin is a simple gallery and everything seems to be functioning correctly. However, I am facing an issue when attemp ...

Querying JSON Data with PHP API

I have been working on creating a query.php file along with a query_result.php page to handle an API JSON feed. My issue is that even when I specify a specific "year" in the query, such as YearBuilt = "1999", the results still include vessels from all year ...

A helpful guide on integrating a Google font into your Next.js project using Tailwind CSS locally

I'm planning to use the "Work Sans" Font available on Google Fonts for a website I'm working on. After downloading the "WorkSans-Black.ttf" file, I created a subfolder named "fonts" within the "public" folder and placed the font file in there. Be ...

The website is failing to extend and reveal content that is being concealed by jQuery

I'm currently diving into the world of Javascript and jQuery, attempting to create a functionality where upon clicking the submit button, the website dynamically expands to display search information. Although the feature is still in progress, I am ut ...

AngularJS: Struggling to Set Up Controller

I recently started my journey with AngularJS a few days back, and I've encountered this frustrating issue. Every time I run into this error: Error: ng:areq Bad Argument Argument 'NewStudentCtrl' is not a function, got undefined All my ot ...

Is there a way to trigger the vue-cli build command automatically when specific files are modified?

One way I can build my JavaScript file is by using the following command: vue build main.js --dist dist --prod --lib While this works, I am looking for a way to automate this process whenever I make changes to my JS or Vue files. I prefer not to rely on ...

What is the most effective way to implement a single modal throughout my web application without having to duplicate HTML code on each page?

After realizing I was repetitively adding the same div to every page for a modal dialog, I decided to place a single div in the site.master page and call it when needed. This method worked fine until I began implementing ajax with partial page updates. H ...

Display Vue component using a string input

Is there a solution to make this non-functioning example work, or is its usage illegal? Vue.component('hello', { template: '<span>Hello world!</span>' }) Vue.component('foo', { data(){ return { ...

Express.js - display the complete information

Trying to display an array of objects (highcharts points) is giving me some trouble. Instead of the actual data, I'm seeing [object Object]. It seems that JSON.stringify() doesn't play well with HTML. util.inspect also doesn't work as expe ...

How can an additional value be sent to the form validation method?

I have created a form group like this: import { checkPasswordStrength } from './validators'; @Component({ .... export class PasswordComponent { ... this.userFormPassword = this.fb.group({ 'password': ['', [ ...

Engaging with the crossrider sidepanel extension

When it comes to the crossrider sidepanel, I prefer using an iframe over js-injected html to avoid interference with the rest of the page. However, I am struggling to establish any interaction between my browser extension and the iframe. I believe adding ...