2017-05-10 6 views
0

일부 자바 스크립트 개체의 매핑/축소를 시도하고 있으며 비참하게 실패하고 있습니다.지도 성능이 좋지 않은 개체의 자바 스크립트 배열을 줄입니다.

[ 
    {table:"a1", data: {colA:1,colB:2,colC:3}}, 
    {table:"a2", data: {colA:2,colB:3,colC:4}}, 
    {table:"a3", data: {colA:3,colB:4,colC:5}} 
] 

Recharts는 결과에 대한 고유의 "이름"키와 소스 데이터 키를 만들어 (다음과 같은 형식의 데이터를 필요로 :

데이터를가 백엔드에서 유래로는 다음과 같이보고 온다 내가 결과 객체를 구축하고, 그 위에마다 반복하고 있습니다 때문에)

[ 
    {name: 'colA', a1: 1, a2: 2, a3: 3}, 
    {name: 'colB', a1: 2, a2: 3, a3: 4}, 
    {name: 'colC', a1: 3, a2: 4, a3: 5} 
] 

나의 현재 솔루션은 현재 O(n^n)입니다. ECMA6/Babel과 Lodash를 사용하고 있습니다. 어떤 지침이라도 대단히 감사하겠습니다! 감사!

편집 : 당신이 중첩 된 3 개 루프를 가지고 있기 때문에 다음 (N^N^n)이 알고리즘의 속도는 실제로 O이고, 시작하려면 내 현재 솔루션

var dest = [] 
Lodash.forEach(source,(o) => { 
    var table = o.table; 
    Lodash.forEach(o.data, (p,q) => { 
    // See if the element is in the array 
    const index = Lodash.findIndex(dest,(a) => {return a.name === q}); 
    if (index === -1) { 
     var obj = {}; 
     obj[table] = Number(p); 
     obj.name = q; 
     dest.push(obj); 
    } else { 
     dest[index][table] = Number(p); 
    } 
    }) 
}); 
+1

정확한 문제가 무엇입니까 ? 퍼포먼스가 필요하다면, raw'for'를 사용하십시오. – estus

+3

현재 솔루션을 게시 할 수 있습니까? – James

+0

현재 코드를 알려주십시오. – Bergi

답변

1

입니다. 내가 그것을 단순화하는 방법은 먼저 객체를 사용하고 객체로부터 배열을 생성하는 것입니다. 그래서 같이 :

function convert(original) { 
 
    var tmp = {}; 
 
    for(var tableIndex in original) { 
 
     var tableObj = original[tableIndex]; 
 
     for(var colKey in tableObj.data) { 
 
      var col = tableObj.data[colKey]; 
 
      if(tmp[colKey] === undefined) { 
 
       tmp[colKey] = {name: colKey}; 
 
      } 
 
      tmp[colKey][tableObj.table] = col 
 
     } 
 
    } 
 

 
    var output = []; 
 
    for(var index in tmp) { 
 
     output.push(tmp[index]); 
 
    } 
 

 
    return output; 
 
} 
 

 
var original = [ 
 
    {table:"a1", data: {colA:1,colB:2,colC:3}}, 
 
    {table:"a2", data: {colA:2,colB:3,colC:4}}, 
 
    {table:"a3", data: {colA:3,colB:4,colC:5}} 
 
] 
 

 
console.log(convert(original));

이 객체에 추가 할 결과 배열을 반복 할 필요성을 제거합니다. 입력 배열과 데이터를 반복 할 때 여전히 O (n^m) + O (l) 조건을 갖지만 모든 반복에서도 결과 배열을 반복하여 더 복잡한 속도 조건을 가지지 않습니다 .

이 함수는 데이터가 테이블마다 다를 수있는 인스턴스도 처리 할 수 ​​있습니다. 따라서 colA와 colB는 가질 수 있지만 colC는 포함하지 않을 수 있습니다. 또는 다른 항목에 colD가있을 수 있습니다.

1

지도를 사용하여 최종 열을 추적하면이 기능을 크게 단순화 할 수 있습니다. 이동 중에지도에 저장하면 일정한 조회 시간의 이점을 얻을 수 있습니다.

테이블 수가 N이고 열의 수가 M이라면 O (N * M)가 표시됩니다.

let input = [ 
 
    { table: "a1", data: { colA: 1, colB: 2, colC: 3 } }, 
 
    { table: "a2", data: { colA: 2, colB: 3, colC: 4 } }, 
 
    { table: "a3", data: { colA: 3, colB: 4, colC: 5 } } 
 
]; 
 

 
let desiredOutput = [ 
 
    { name: 'colA', a1: 1, a2: 2, a3: 3 }, 
 
    { name: 'colB', a1: 2, a2: 3, a3: 4 }, 
 
    { name: 'colC', a1: 3, a2: 4, a3: 5 } 
 
]; 
 

 
let keys = null; 
 
let map = null; 
 

 
input.forEach(row => { 
 
    if (map === null) { 
 
    // Cache the column names 
 
    keys = Object.keys(row.data); 
 
    
 
    // Generates objects such a `{ name: 'colA' }` 
 
    // and stores them at a key of 'colA' 
 
    map = keys 
 
     .reduce((o, k) => (o[k] = { 
 
     name: k 
 
     }, o), {}); 
 
    } 
 

 
    // For each column ('colA', 'colB', etc.) 
 
    keys.forEach(key => { 
 
    // Create a new property for the table name 
 
    // ('a1', 'a2', etc.) 
 
    // and copy the matching column value from the input 
 
    map[key][row.table] = row.data[key]; 
 
    }); 
 
}); 
 

 
// Convert the map to an array of just the values 
 
let output = Object.values(map); 
 
console.log(JSON.stringify(output) === JSON.stringify(desiredOutput)); 
 
console.log(output);

+0

reduce와 forEach와 같은 몇몇 헬퍼 메소드를 잘 사용하십시오. 그들도 자신의 간접비를 생산한다는 것을 명심하십시오. 우리의 솔루션을 모두 테스트 한 결과 속도는 1,500ms에서 1,000,000 회였습니다. 내 반복 횟수는 900ms였습니다. 우리의 유일한 차이점은 바닐라 자바 ​​스크립트를 더 많이 사용하는 동안 도우미 메서드를 사용한다는 것입니다. 편리함에주의하십시오. –

+0

@PeterLaBanca 사실입니다. 데이터 집합이 상당히 크고 속도가 절대적으로 필요한 경우 도우미 메서드는 피해야합니다. –