2014-01-18 2 views
3

두 배열간에 상호 배타적 인 값을 0으로 채우는 고성능 방법을 찾고 있습니다. 이 데이터는 모든 x 값에 대한 항목이 있어야하는 JS 차트 용입니다.자바 스크립트 : 배열 사이에 누락 값 채우기

하기 전에 :

obj1 = [{x:1, y:1}, {x:3, y:2}]; 
obj2 = [{x:2, y:2}, {x:4, y:4}]; 

후 : 예는 더 나은이 설명 할 수 내가 루프 중첩 사용

obj1 = [{x:1, y:1}, {x: 2, y:0}, {x:3, y:2}, {x:4, y:0}]; 
obj2 = [{x:1, y:0}, {x: 2, y:2}, {x:3, y:0}, {x:4, y:4}]; 

이 나 자신을 할 수 있지만 & 항목이 증가 개체의 수, 벽 등 시간이 용납 할 수 없을 정도로 높습니다. 수천 개의 항목으로 채워지지 않는 데이터 세트에서 벽 시간은 10 초를 넘었습니다.

jQuery와 밑줄과 같은 일부 JS 라이브러리를 살펴 봤지만 더 나은 기능을 수행하는 것은 분명하지 않습니다.

업데이트 : 모든 답변 주셔서 감사합니다. 나는 그것들을 시험해보고 가장 좋은 결과를 답으로 표시 할 것입니다. x 값에 대한 참고 사항 : 반드시 단조롭게 증가 할 필요는 없습니다 (obj1 & 2는 둘 다 x 값을 건너 뛸 수 있습니다.). x 축은 반드시 숫자 일 필요는 없으며 날짜 일 수도 있습니다. 다행히도 하나 이상의 답변이 이에 적합합니다.

답변

1

기본적으로 모든 값의 해시와 각 개체의 모든 값의 해시를 만듭니다. 그런 다음 '개인의 해시 여기

// hash of unique x values 
var xValues = {}; 

// store each distinct x value 
walk(obj1, 'obj1'); 
walk(obj2, 'obj2'); 

// fill each array with missing values 
fill(obj1, 'obj1'); 
fill(obj2, 'obj2'); 

function walk(obj, nm){ 
    xValues[ nm ] || (xValues[ nm ] = {}); 
    xValues.all || (xValues.all = {}); 

    for(var i=0, l=obj.length; i<l; i++){ 
     xValues[ nm ][ obj[ i ].x ] = 1; 
     xValues.all [ obj[ i ].x ] = 1; 
    } 
} 

function fill(obj, nm){ 
    for(var key in xValues.all){ 
     if(!(key in xValues[ nm ])){ 
      obj.push({ x : key, y : 0 }); 
     } 
    } 
} 
+0

이 방법은이 테스트 데이터 세트와 CPU에서 제로 - 필 시간을 5 초에서 밀리 초로 줄입니다.각 배열 (데이터 레이어)에서 모든 x 값의 사전을 만들었습니다. 또한 조회 속도를 높이기 위해 각 데이터 계층에 대한 임시 사전을 만들었습니다 (배열을 반복하거나 indexOf를 사용하지 않아야 함). 찾는 것은 매우 빠릅니다. for (all_x_vals의 var 항목) {if (typeof tmp_dict [entry] == 'undefined') ZeroFillArrayEntry(); } ----- 정확한 코드는 아니지만 잘하면 포인트를 얻는다 – pmont

-1

에 존재하지 않는'모든 '해시의 해시와 개체를 채우는 것은 그것을하는 또 다른 방법입니다. 성능을 위해 가능한 한 많이 구현 된 메소드를 사용합니다.

var obj1 = [{x:1, y:1}, {x:3, y:2}]; 
var obj2 = [{x:2, y:2}, {x:4, y:4}]; 

// get the x values from each array 
var xGetter = function(i) { return i.x; }; 
var obj1xs = obj1.map(xGetter); 
var obj2xs = obj2.map(xGetter); 

// get the joined array 
var joined = obj1.concat(obj2); 

// get all x values 
var xs = joined.map(xGetter); 

// get the min and max values of x from both arrays combined 
var min = Math.min.apply(null, xs), max = Math.max.apply(null, xs), i = min; 

// fill the missing x values with zero y value 
if(min < max) { 
    while(i<=max) { 
    if(obj1xs.indexOf(i) === -1) obj1.push({x: i, y: 0}); 
    if(obj2xs.indexOf(i) === -1) obj2.push({x: i, y: 0}); 
    i++; 
    } 
} 

// sort the arrays 
var mySorter = function(a, b) { return a.x - b.x; }; 
obj1 = obj1.sort(mySorter); 
obj2 = obj2.sort(mySorter); 

출력은 다음과 같습니다

obj1 => [{"x":1, "y":1}, {"x":2, "y":0}, {"x":3, "y":2}, {"x":4, "y":0}] 
obj2 => [{"x":1, "y":0}, {"x":2, "y":2}, {"x":3, "y":0}, {"x":4, "y":4}] 
+1

이것은 OP와 비슷한 성능 문제가있을 것입니다. 'indexOf'의 –

0

데이터가 사전 정렬 가정을 만드는 또 다른 대답을 추가. 미리 정렬되지 않은 경우이를 정렬하면됩니다. 그것은 최소한의 메모리 사용의 이점이 매우 빠르고, 설치를 완료하고 데이터가 정렬됩니다 :

var maxX = Math.max(
     obj1[ obj1.length-1 ].x 
    , obj2[ obj2.length-1 ].x 
); 

fill(obj1, maxX); 
fill(obj2, maxX); 

function fill(obj, max){ 
    for(var i=0; i<max; i++){ 
     if(!obj[i] || (obj[i].x !== i+1)){ 
      obj.splice(i, 0, { x:i+1, y:0 }); 
     } 
    } 
} 
+0

으로 인해 "실패"코드가 있습니다. 게시 한 답변이 본질적으로 너와 똑같아. 너의 downvote을 이해하지 마십시오. 이것은 가장 간단한 시도 인 것 같습니다. +1 – basilikum

0

방법과 배열로 변환)

1 (의사 포함) 다음과 같은 접근 방식에 대한 x는 색인입니다.

var arr = []; 
for each object in input_list 
    arr[object.x] = object.y 

2) 상기 어레이를 통해 반복 다시 오브젝트

result = arr2.map -> return { x : index, y: value } 

PS로 제로

arr2 = arr.map -> return (typeof value !== 'undefined') value : 0 

3

) 배열 변환과 undefined을 채우
당신이 그것을 최적화 또한 2 단계와 3 단계를 결합하여 다른 루프를 저장합니다.

+1

OP가 질문하지 않는 한 coffeescript로 대답하지 마십시오. 'arr.map -> return'과 같은 것은 –

+1

구문에 익숙하지 않은 사람들에게는 명확하지 않습니다. 내 대답에 언급). OP는 "teh codez"가 아니라 지침을 요구하고 있습니다. –

관련 문제