Search code examples
javascriptajaxcodeigniter-3

triggering my fetched data with my script that combines data with the same value


my target is to combine 2 arrays in 1 array if they have the same level.

For example i have testing 1 = level 1 and testing 4 = level 1. They'll be joined in 1 array because they have the same level.

The below script I provided is what combines 2 arrays in 1 if they have the same level. How can I achieve the target that I stated above? Thank you, guys. I provided my codes and images below.

[An Image of what I'm fetching] [An Image of my target when 2 scripts are joined]

Ajax:

  var ajaxResult=[]; // the pushed data will be saved here
    var save_method; 
    var table;
    var base_url = '<?php echo base_url();?>';
     
    $(document).ready(function() {
     
        //datatables
        table = $('#entry_list').DataTable({ 
            dom: 'lBfrtip',
            buttons: [
                'print', 'csv', 'copy', 'excel', 'pdfHtml5'
            ],
           
            "processing": false, 
            "serverSide": true,     
            "order": [], 
            
     
        
            "ajax": {
                "url": "<?php echo site_url('controller/fetch_players')?>",
                 "type": "POST",
                 async:true,
                 dataType: "json", 
                 
             
                 success: function(data){
             
                 ajaxResult.push(data); // I'm pushing my data to my ajaxResult variable
       
        
       console.log(ajaxResult);
                  
               
               
                },
                
            },
     
           
            "columnDefs": [
                { 
                    "targets": [ 0 ], 
                    "orderable": false,
                },
                { 
                    "targets": [ -1 ], 
                    "orderable": false, 
                },
     
            ],
     
        });
});

script:

//script for combiningng data in 1 array if they have the same level. 
    

const ajaxResult= [] // I'm calling here what I fetched on my ajax.
        
        const matching = (list, keyGetter) => {
            let mapping = {};
            const map = new Map();
            list.forEach((item) => {
                const key = keyGetter(item);
                const collection = map.get(key);
                if (!collection) {
        
                    map.set(key, [item]);
                } else {
        
                    collection.push(item);
                }
            });
        
            Array.from(map).map(([key, value]) => Object.assign(mapping, { [key]: value }));
            return mapping
        }
        
        const result = matching(ajaxResult, ({ level}) => { return level});
        
        console.log("RESULT", result);  // when i do console.log, the result me be testing 1 and testing 4 in 1 array, so is testing 2 and testing 4

Solution

  • You can use array.reduce to achieve the desired behaviour.

    const source = [
        {id: 1, name: 'player1', level: 1},
        {id: 2, name: 'player2', level: 2},
        {id: 3, name: 'player3', level: 3},
        {id: 4, name: 'player4', level: 1},
        {id: 5, name: 'player5', level: 2},
        {id: 6, name: 'player6', level: 3},
    ]
    
    const combine = (source) => {
        return source.reduce((acc,curr) => {
            if(acc[curr.level]) 
                acc[curr.level].push(curr);
            else
                acc[curr.level] = [curr];   
            return acc;
        },{})
    }
    
    console.log('Result', combine(source));

    Explanation:

    A reducer iterates through and array and for each iteration, it can hold the result of the previous computation. Using this idea, we first check if we have an array for the level computed, if yes, we just push the current object into the array. If not, we create a new array with the current object as the first element.

    P.S: I'd recommend adding logs to check values of acc and curr on each iteration to understand this better.

    Edit: Showcasing how to use with Ajax response:

    let ajaxResult = []; // the pushed data will be saved here
    let save_method;
    let table;
    let base_url = "<?php echo base_url();?>";
    let result = [];
    
    const combine = (source) => {
      return source.reduce((acc, curr) => {
        if (acc[curr.level])
          acc[curr.level].push(curr);
        else
          acc[curr.level] = [curr];
        return acc;
      }, {})
    }
    
    $(document).ready(function() {
      //datatables
      table = $("#entry_list").DataTable({
        dom: "lBfrtip",
        buttons: ["print", "csv", "copy", "excel", "pdfHtml5"],
    
        processing: false,
        serverSide: true,
        order: [],
    
        ajax: {
          url: "<?php echo site_url('controller/fetch_players')?>",
          type: "POST",
          async: true,
          dataType: "json",
    
          success: function(data) {
            ajaxResult.push(data); // I'm pushing my data to my ajaxResult variable
            result = combine(ajaxResult); // Cleanup your data here. 
          },
        },
    
        columnDefs: [{
            targets: [0],
            orderable: false,
          },
          {
            targets: [-1],
            orderable: false,
          },
        ],
      });
    });