✏️8.8 반복문을 파이프라인으로 바꾸기 (Replace Loop with Pipeline)

리팩터링 전

const names = [];
for (const i of input) {
  if (i.job === "programmer")
    names.push(i.name);
}

리팩터링 후

const names = input
.filter(i => i.job === "programmer")
.map(i => i.name)
;

🧷 배경

컬렉션 파이프라인을 이용하면 처리 과정을 일련의 연산으로 표현할 수 있다.

객체 컬렉션을 순회할 때 반복문을 사용하라고 배웠다. 대표적인 연산은 mapfilter다.

map

함수를 사용해 입력 컬렉션의 각 원소를 반환

filter

함수를 사용해 입력 컬렉션을 필터링해 부분집합을 만든다. 이 부분 집합은 파이프라인의 다음 단계를 위한 컬렉션으로 쓰인다.

논리를 파이프라인으로 표현하면 이해하기 훨씬 쉬워진다. 객체가 파이프라인을 따라 흐르며 어떻게 처리되는지를 읽을 수 있기 때문이다.

🧷 절차

1. 반복문에서 사용하는 컬렉션을 가리키는 변수를 하나 만든다.

2. 반복문의 첫 줄부터 시작해서 각각의 단위 행위를 적절한 컬렉션 파이프라인 연산으로 대체한다. 이때 컬렉션 파이프라인연산은 1에서 만든 반복문 컬렉션 변수에서 시작하고, 이전 연산의 결과를 기초로 연쇄적으로 수행한다.

3. 반복문의 모든 동작을 대체했다면 반목문 자체를 지운다.

🧷 예시

예시를 위한 데이터

office, country, telephone

Chicago, USA, +1 312 373 1000
Chicago, USA, +1 312 373 1000
Chicago, USA, +1 312 373 1000
... (데이터0
function acquireData(input) {
  const linew = input.split =("\n");  // 컬렉션
  let firstLine = true;
  const result = [];
  for (const line of lines) {  // 반복문
    if (firstLine) {
      firstLine = false;
      continue;
    }
    if (line.trim() === "") continue;
    const record = line.split(",");
    if (record[1].trim() === "India") {
      result.push({city: record[0].trim(), phone: recored[2].trime()});
    }
  }
  return result;
}
  1. 반복문에서 사용하는 컬렉션을 가리키는 별도 변수를 새로 만들자. 이 변수를 루프 변수라 하겠다.

function acquireData(input) {
  const linew = input.split =("\n");  
  let firstLine = true;
  const result = [];
  // 루프 변수
  const loopItems = lines;
  for (const line of loopItems) {  
    if (firstLine) {
      firstLine = false;
      continue;
    }
    if (line.trim() === "") continue;
    const record = line.split(",");
    if (record[1].trim() === "India") {
      result.push({city: record[0].trim(), phone: recored[2].trime()});
    }
  }
  return result;
}
  1. 반복문에서 slice() 연산을 루프 변수에서 수행하고 반복문에서 if 문을 제거하자.

function acquireData(input) {
  const linew = input.split =("\n");  
  const result = [];
  const loopItems = lines
    .slice(1)
  for (const line of loopItems) {  
    if (line.trim() === "") continue;
    const record = line.split(",");
    if (record[1].trim() === "India") {
      result.push({city: record[0].trim(), phone: recored[2].trime()});
    }
  }
  return result;
}
  1. trime() 연산 대신 filter 연산으로 대체한다.

function acquireData(input) {
  const linew = input.split =("\n");  
  const result = [];
  const loopItems = lines
    .slice(1)
    .filter(line => line.trim() != "")
    ;
  for (const line of loopItems) {  
    const record = line.split(",");
    if (record[1].trim() === "India") {
      result.push({city: record[0].trim(), phone: recored[2].trime()});
    }
  }
  return result;
}

파이프라인을 사용할 때는 문장 종료 세미콜론(;)을 별도 줄에 적어주면 편하다.

  1. map()연산과 filter() 연산을 사용한다.

function acquireData(input) {
  const linew = input.split =("\n");  
  const result = [];
  const loopItems = lines
    .slice(1)
    .filter(line => line.trim() != "")
    .map(line => line.split(","))
    .filter(recored => recored[1].trime() === "India")
    .map(record => ({city: record[0].trim(), phone: recored[2].trime()}))
    ;
  for (const line of loopItems) {  
    const record = line;
    result.push(line);
  }
  return result;
}
  1. 결과를 누적변수에 추가한다.

function acquireData(input) {
  const linew = input.split =("\n");  
  const result = [];
  const result = lines
    .slice(1)
    .filter(line => line.trim() != "")
    .map(line => line.split(","))
    .filter(recored => recored[1].trime() === "India")
    .map(record => ({city: record[0].trim(), phone: recored[2].trime()}))
    ;
  return result;
}

Last updated