지난 시간으로 table post를 마무리 하려고 했는데 치명적 문제가 발생했네요. 지난 방식으로 하면 정렬이 문자 or 숫자가 한자리면 상관없는데 한자리 이상이면 이게 문자열 정렬인지 숫자 정렬인지 명확하지 않고 문자열 정렬으로 진행 되는 것 같더군요. 즉, 숫자의 경우 1로시작하는 숫자가 크고 2로 시작하는 숫자 작을 때 작은 순으로 정렬한다면 2가 먼저 나와야 하는데 1로 시작하는 숫자가 먼저 나오게 되는 치명적 문제를 갖고 있네요. 그래서 숫자 정렬과 문자열 정렬를 구분하여 정렬이 이루어지도록 수정했습니다.
위 post로 정렬을 진행할 경우 한자리 문자 or 숫자의 경우는 정상적으로 출력 됩니다. 하지만 두자리 이상의 경우는 각 자리의 순차적 비교이기 때문에 문자열은 상관없는데 숫자의 경우는 작은수 순서로 정렬 할 경우 이상한 정렬이 발생합니다.
.on('click', function (d) {
if (sortstate) {
rows.sort(function(a, b) { return b[d] > a[d]; });
sortstate = false;
} else {
rows.sort(function(a, b) { return b[d] < a[d]; });
sortstate = true;
}
});
위 코딩으로 정렬을 시도하면 다음과 같은 결과를 얻게 됩니다.
위 실험에서 a 쪽을 오름차순 or 내림차순으로 정렬을 시키면 보시는 것처럼 20이란 숫자가 중간에 배치되게 됩니다. 원래는 11200->702->20 or 20->702->11200순으로 정렬을 해야 하는데 숫라고 인식않고 이 자체를 문자열 비교가 이루어지는 것 같더군요.
숫자형 정렬과 문자열 정렬을 구분하여 정렬을 해야 합니다.
.on('click', function (d) {
sortstate = !sortstate;
rows.sort(function(a,b){
if(isNaN(a[d])){
if (sortstate) return b[d] > a[d];
else return a[d] > b[d];
}else{
if (sortstate) return b[d] - a[d];
else return a[d] - b[d];
}
});
});
위와 같이 isNaN()값으로 문자열인지 숫자형인지를 구분하여 정렬을 시도하니깐 정상적으로 정렬이 이루어지네요. 지난 시간에 정렬을 몇가지 표현했는데 그 안에 숫자 정렬이 들어 있었더군요. 이렇게 해서 해결 했네요.
[data.csv]
이름,a,b,c
홍길동,11200,90,1910
강감찬,702,12100,720
김수로,20,620,95
[전체소스]
<body>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script type="text/javascript" src="http://d3js.org/d3.v5.min.js"></script>
<script type="text/javascript">
d3.csv("data.csv").then(function(data){
var sortstate = true;
var title = d3.keys(data[0]);
var table = d3.select('body').append('table')
.attr("class","table");
var thead = table.append('thead');
var tbody = table.append('tbody');
var header = thead.append('tr')
.selectAll('th')
.data(title).enter()
.append('th')
.text(function (d) {return d;})
.on('click', function (d) {
sortstate = !sortstate;
rows.sort(function(a,b){
if(isNaN(a[d])){
if (sortstate) return b[d] > a[d];
else return a[d] > b[d];
}else{
if (sortstate) return b[d] - a[d];
else return a[d] - b[d];
}
});
});
var rows = tbody.selectAll('tr').data(data)
.enter()
.append('tr');
var cells = rows.selectAll('td')
.data(function (d) {
return title.map(function (title) {
return { 'title': title, 'value': d[title]};
});
})
.enter()
.append('td')
.text(function (d) { return d.value;});
});
</script>
</body>
[결과]
이제야 원하는 정렬이 되었네요.
table 정렬 post를 수정할까도 생각했는데 정렬이 틀린 것은 아니고 지난 post의 정렬은 한자리일때는 문자 or 숫자는 구분하지 않고 정렬을 하기 때문에 정상적으로 출력했었고요. 원리를 이해하는 위한 post이기 때문에 그냥 뒀네요. 그 원리를 이해했기에 문제가 발생했을 때 바로 수정이 될 수 있었네요.