[개발일지] - 406
오자마자 List<Map> 형태로 넘어오는 데이터 정렬 방식을 구상했는데
처음에는 정렬 기준이 되는 필드들을 Key로 하는 Map에 한번 더 각각의 Map을 담아주고
Key들만 정렬해서 하나씩 뽑아서 map에서 값을 가져온 다음 List에 추가하는 방식으로 순서를 정할까 했는데
가독성도 떨어지는 것 같고 apex에서 정식 처리 방식은 어떤게 있는지 궁금해서 확인해봤다.
기존에 임시 테스트용으로 생성한 데이터를 통해서 아래와 같이 정렬처리가 됐는데
메서드가 아니라 클래스로 추가해야 하는 부분이 조금 특이하긴 했고
내부에 사용되는 객체 형태가 실제 들어온 Wrapper가 아니라는 특이사항들을 제외하고는
주어진 값을 통해서 정상적으로 정렬이 되는 것이 확인되었기 때문에
아래 메서드를 변형해서 정상 정렬 후 해당 값을 재할당해서 사용하는 방식으로 순서를 확정지었다.
List<Map<String, String>> mapList = new List<Map<String, String>>();
Map<String, String> aaa = new Map<String, String>();
aaa.put('x', '000123');
Map<String, String> bbb = new Map<String, String>();
bbb.put('x', '000124');
Map<String, String> ccc = new Map<String, String>();
ccc.put('x', '000125');
Map<String, String> ddd = new Map<String, String>();
ddd.put('x', '000126');
Map<String, String> eee = new Map<String, String>();
eee.put('x', '000127');
Map<String, String> fff = new Map<String, String>();
fff.put('x', '000128');
mapList.add(bbb);
mapList.add(fff);
mapList.add(ccc);
mapList.add(eee);
mapList.add(aaa);
mapList.add(ddd);
public class MapWrapper implements Comparable {
public Map<String, String> mapData;
public MapWrapper(Map<String, String> mapData) {
this.mapData = mapData;
}
public Integer compareTo(Object compareTo) {
MapWrapper compareMapWrapper = (MapWrapper)compareTo;
String aValue = this.mapData.get('x');
String bValue = compareMapWrapper.mapData.get('x');
return aValue.compareTo(bValue);
}
}
List<MapWrapper> mapWrapperList = new List<MapWrapper>();
mapWrapperList.add(new MapWrapper(bbb));
mapWrapperList.add(new MapWrapper(fff));
mapWrapperList.add(new MapWrapper(ccc));
mapWrapperList.add(new MapWrapper(eee));
mapWrapperList.add(new MapWrapper(aaa));
mapWrapperList.add(new MapWrapper(ddd));
mapWrapperList.sort();
System.debug(mapWrapperList);
이후 정렬 방식이 잘 적용되었는지 테스트를 하려고 했는데
상위개체 상태 변경이 중요한 로직 중 하나였기 때문에
해당 개체 생성 요청을 한 다음 만들어진 필드에 다양한 JSON을 랜덤 순서로 넣어봤는데
확실히 마지막 값을 기준으로 상태가 결정되도록 잘 적용되는 것을 확인할 수 있었다.
이후 날짜, 랜덤값 등을 포함해서 만든 Key값 반환 부분을 고민했는데
생성 로직도 존재하지 않고 Key를 만들어서 주는 것이 아니었기 때문에
이걸 어떻게 만들어야 하는지 고민하다 AutoNum쪽을 확인했다.
하지만 AutoNum의 경우 YYMMDD00 형태로 들어갈 경우
24081201처럼 숫자가 99까지는 잘 들어가지만
그 이후 100이 넘는 순간부터 240812100처럼 자릿수를 지 멋대로 바꿔버리는 문제가 있었다.
이 부분을 제한할 수 있는 방법에 대해서 여러가지로 검색을 시도했지만
2013년인가 그 이전부터 이것에 대한 항의들이 있다는 것 외에 개선되었다는 내용은 볼 수 없었고
결국 AutoNum은 그대로 추가해서 숫자로만 생성되게 관리하고
After Insert를 통해서 해당 값에서 제한 자릿수(10의 경우 %100)를 제거한 나머지 값을 사용하기로 했다.
해당 AutoNum값 필드, Key값 저장 필드를 생성해주려고 하던 중 기존 데이터 삭제요청이 왔는데
사실 삭제요청이라기보다 삭제를 해야 다음 절차가 가능하다고 내가 SAP과 고객사의 대화를 중단시킨 것에 가까웠다.
어쨌거나 동의를 받고 Key를 엉망으로 넣어서 꼬여있는 이전 데이터를 밀어버리기로 했는데
쿼리에서는 날짜 값을 임의뢰 지정하는 것이 아니라 newInstance를 생성해야 지정되는 것 같았다.
DateTime targetDateTime = DateTime.newInstance(2024, 8, 2, 15, 13, 37);
List<ObjectName__c> objList= [SELECT Id
FROM ObjectName__c
WHERE CreatedDate < :targetDateTime
ORDER BY CreatedDate DESC];
delete objList;
이후 개발쪽에서 추가로 문의하는 부분과 요청사항들을 답변 및 확인했는데
추가로 개발해야 하는 부분들의 연결점이 많기도 했고
PriceBookEntry 등 추가 레코드들도 여러개 생성해야 했지만
그래도 난이도가 높은 것은 아니라서 키 필드 관련 로직 처리 및 유지보수 답변 후 진행하기로 했다.
이후 AutoNum을 사용해서 키 필드를 생성하려고 시도했지만
안타깝게도 문제가 있어서 진행되지 못하고 대응책만 열심히 검색했는데
2013년 이전부터도 고객사에서도 말이 많아서 다들 항의하던 부분이지만
그냥 묵살되고 여태까지 넘어온 문제 같았다.
결국 AutoNum으로 관리를 한 다음
Trigger를 통해서 해당 값에 %처리로 원하는 자릿수를 맞춰주고
날짜 또는 키에 맞는 형태값들을 수동으로 합쳐서 필드에 업데이트하기로 했다.
의외로 Apex에서는 %처리가 먹히지 않았기 때문에
숫자로 바꾼 값을 가지고 어떻게 할지 잠깐 고민했는데
이걸 사실 문자열로 뒤에 n개의 글자만 가져온 다음 0을 앞에 붙여주는 방식으로 하면 됐고
leftPad를 사용해서 앞에 0을 붙일 수 있게 처리한 다음 해당 값을 업데이트 하는 방식으로 해결했다.
사실 중간에 에러가 발생해서 인터페이스가 되지 않았는데
after trigger 내부에서는 가져온 값들의 필드를 변경할 수 없었고
new ObjectName() 형태로 Id와 변경할 값을 넣은 레코드들을 모아서 업데이트 처리해야 했다.
(1).백준 11404번 플로이드는 정상적인 플로이드 문제로
도시의 개수와 버스 노선과 비용의 개수가 주어질 때
각 도시별로 가장 적은 금액으로 갈 수 있는 비용들을 출력해야 하는 문제였다.
처음에는 간단하게 플로이드 워셜 느낌으로 진행하다가
할당하는 부분은 0 또는 1이 아닌 비용이기 때문에 조건 하 최대값 천만을 넣었기 때문에
최소값을 출력하는 방식으로 비교하면서 각 경로를 순회했고(경로당 두개 이상의 다른 가격 존재 가능)
플로이드 워셜로 금액을 결정해준 다음 형태에 맞춰 출력했는데
마지막쯤 갑작스럽게 오답이 나와서 문제를 자세히 읽어보니
갈 수 없는 경로는 0원 처리해야 했기 때문에 초반에 설정한 천만이라는 값을 찾아 0으로 변경 후 출력했다.
const input = `5
14
1 2 2
1 3 3
1 4 1
1 5 10
2 4 2
3 4 1
3 5 1
4 5 3
3 5 10
3 1 8
1 4 2
5 1 7
3 4 2
5 2 4`.split('\n')
const vertex = Number(input[0])
const map = []
for(let i = 0 ; i < vertex ; i++){
map.push(new Array(vertex).fill(10000000))
map[i][i] = 0
}
for(let i = 2 ; i < input.length ; i++){
[start, end, cost] = input[i].split(' ').map(Number)
map[start-1][end-1] = Math.min(map[start-1][end-1], cost)
}
for(let i = 0 ; i < vertex ; i++){
for(let j = 0 ; j < vertex ; j++){
for(let k = 0 ; k < vertex ; k++){
map[j][k] = Math.min(map[j][k], map[j][i] + map[i][k])
}
}
}
for(let i = 0 ; i < vertex ; i++){
for(let j = 0 ; j < vertex ; j++){
if(map[i][j] == 10000000){
map[i][j] = 0
}
}
}
console.log(map.map(el => el.join(' ')).join('\n'))