简体   繁体   中英

Is there a way to de-dupe a javascript array and combine values of the data?

I'm using an ajax request to grab some XML data which I then need to push into a chart in fusioncharts.

The XML data is formatted as [time taken], [work done], [which team done for], [who did it] (see below).

I'm iterating over the XML and then building the array using the code below:

 //Time Recorded
                    if (columnidchecker == 7781) {
                        timearray.push($j(this).find('displayData').text());
                        temp1 = $j(this).find('displayData').text();
                    }
                    //Type of Activity
                    if (columnidchecker == 7782) {
                        activityarray.push($j(this).find('displayData').text());
                        temp2 = $j(this).find('displayData').text();
                    }
                    //Team Done For
                    if (columnidchecker == 7783) {
                        subjectarray.push($j(this).find('displayData').text());
                        temp3 = $j(this).find('displayData').text();
                    }
                    //Name
                    if (columnidchecker == 7777) {
                        internalclientarray.push($j(this).find('displayData').text());
                        temp4 = $j(this).find('userDisplayName').text();
                    }
                });
                //PUSH INTO A NEW ARRAY WHICH CAN THEN BE SORTED AND DE-DUPED WITH TIME COMBINED AGAINST ACTIVITY / TEAM.
                objectarray.push([temp1, temp2, temp3, temp4]);

This builds an array of entries from the XML which basically outputs to something which looks like this:

0: (4) ["1.50", "Ad-hoc queries or calls", "Team 1", "James"]
    1: (4) ["2.50", "Ad-hoc queries or calls", "Team 1", "James"]
    2: (4) ["1.00", "Advice", "Team 2", "James"]
    3: (4) ["3.50", "Meeting (External 3rd Party)", "Team 1", "James"]
    4: (4) ["1.20", "Administration", Team 2", "James"]
    5: (4) ["5.50", "Advice", "Team 1", "John"]

I'm trying to build a chart in fusioncharts which needs the format as shown below (ignore foot stuffs - it's taken straight from the fusioncharts help pages!).

{
    "chart": {
        "theme": "fusion",
        "caption": "Revenue split by product category",
        "subCaption": "For current year",
        "xAxisname": "Quarter",
        "yAxisName": "Revenues (In USD)",
        "showSum": "1",
        "numberPrefix": "$"
    },
    "categories": [
        {
            "category": [
                {
                    "label": "Q1"
                },
                {
                    "label": "Q2"
                },
                {
                    "label": "Q3"
                },
                {
                    "label": "Q4"
                }
            ]
        }
    ],
    "dataset": [
        {
            "seriesname": "Food Products",
            "data": [
                {
                    "value": "11000"
                },
                {
                    "value": "15000"
                },
                {
                    "value": "13500"
                },
                {
                    "value": "15000"
                }
            ]
        },
        {
            "seriesname": "Non-Food Products",
            "data": [
                {
                    "value": "11400"
                },
                {
                    "value": "14800"
                },
                {
                    "value": "8300"
                },
                {
                    "value": "11800"
                }
            ]
        }
    ]
}

The problem i'm having is that I cannot work out how to take the array of data with times, activity, team, name and push them into categories.

I think the first step is to create a new array of names which can be pushed into the "Category" data field in fusioncharts.

I then need a way in which to take the times being recorded against each activity and for each team and make sure it's assigned to the right person within the stacked bar chart and combine the amount of time spent. (ie "James" spent a total of 4 hours doing "Ad Hoc Queries and Calls" for Team 1 but this is split across two time entries so I need a way in which to combine them into one.)

Any help on this would be massively appreciated.

I can de-dupe the names to create a new array by using the following code:

 namesarray.push(temp4);
 uniq = [...new Set(namesarray)];

but after that it starts getting pretty complicated.

Maybe this can help you along the way. It's probably not exactly in the form you want it, but it demonstrates how you could break the problem down into smaller parts.

Pseudo-code:

  1. get the unique names.
  2. get the unique "task" names (for lack of a better word)
  3. for each unique person name:

    3.1. get the data rows for that person

    3.2 for each of all unique tasks names:

    1. find the person data rows matching the task name
    2. sum the duration of those data rows

 const testData = [ [ "1.50", "Ad-hoc queries or calls", "Team 1", "James" ], [ "2.50", "Ad-hoc queries or calls", "Team 1", "James" ], [ "1.00", "Advice", "Team 2", "James" ], [ "3.50", "Meeting (External 3rd Party)", "Team 1", "James" ], [ "1.20", "Administration", "Team 2", "James" ], [ "5.50", "Advice", "Team 1", "John" ] ]; const columnIndexByName = { TASK_DURATION: 0, TASK_NAME: 1, FOR_WHICH_TEAM: 2, PERSON_DOING_TASK: 3 }; const sum = (acc, next) => acc + next; const uniqueNames = [...new Set(testData.map(row => row[columnIndexByName.PERSON_DOING_TASK])) ]; const uniqueTaskNames = [...new Set(testData.map(row => row[columnIndexByName.TASK_NAME])) ]; let result = {}; uniqueNames.forEach(personName => { const personDataRows = testData.filter(row => row[columnIndexByName.PERSON_DOING_TASK] === personName); let taskDurationsByTaskName = {}; uniqueTaskNames.forEach(taskName => { const taskRows = personDataRows.filter(row => row[columnIndexByName.TASK_NAME] === taskName); const taskDurations = taskRows.map(row => Number.parseFloat( row[columnIndexByName.TASK_DURATION] )); const taskTotalDuration = taskDurations.reduce(sum, 0); taskDurationsByTaskName[taskName] = taskTotalDuration; }) result[personName] = taskDurationsByTaskName; }) const renderData = data => document.querySelector("#output").innerHTML = JSON.stringify(data, null, 2); renderData(result); 
 <pre id="output"></pre> 

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