Skip to content

Instantly share code, notes, and snippets.

@ljlm0402
Last active April 7, 2022 09:13
Show Gist options
  • Save ljlm0402/46560c4b6d329148aaee91dd4053401d to your computer and use it in GitHub Desktop.
Save ljlm0402/46560c4b6d329148aaee91dd4053401d to your computer and use it in GitHub Desktop.
알고리즘
  • type이 일치하는 오브젝트 객체 안에 key의 배열을 생성하여 추가하시오.

problem

/* before */
[
  {
    key: 'all',
    value: 'Window',
    type: 'include'
  },
  {
    key: 'agentName',
    value: 'agent1',
    type: 'include'
  },
  {
    key: 'agentName',
    value: 'agent2',
    type: 'include'
  },
  {
    key: 'agentIp',
    value: '127.0.0.1',
    type: 'exclude'
  }
]

/* after */
{
  include: {
    all: ['Window'],
    agentName: ['agent1', 'agent2']
  },
  exclude: {
    agentIp: ['127.0.0.1']
  }
]

sloution

(1) reduce 4st

const result = data.reduce((acc, { key, value, type }) => {
  acc[type] = acc[type] || {};
  acc[type][key] = acc[type][key] || [];
  acc[type][key].push(value);
  return acc;
}, {});

(2) for() inner 2st

let obj = {};
for (let i = 0, key = '', value = '', type = '';
    i < data.length && ({ key, value, type } = data[i],
     (obj[type] || (o = {}, obj[type] = o, o)),
     (obj[type][key] || (acc = [], obj[type][key] = acc, acc)).push(value));
     i++) {}

(3) for() outner 3st

let obj = {};
for (let { key, value, type } of data) {
  obj[type] || (o = {}, obj[type] = o, o);
  (obj[type][key] || (acc = [], obj[type][key] = acc, acc)).push(value);
}

(4) function + slice 1st

const parsedata = (
  data, 
  obj = { include: {}, exclude: {} }, 
  fn = (data, obj, datum = data[0]) => 
    data.length === 0 ? obj : fn(data.slice(1), {
      ...obj,
      [datum.type]: {
        ...obj[datum.type],
        [datum.key]: [...(obj[datum.type][datum.key] || []), datum.value]
      }
    }),
    result = fn(data, obj)
  ) => result;

Problem

/* before */
{
  Lyon: 'France',
  Berlin: 'Germany',
  Paris: 'France'
}

/* after */
{
  France: ['Lyon', 'Paris'],
  Germany:  ['Berlin']
}

Solution

const cities = {
  Lyon: 'France',
  Berlin: 'Germany',
  Paris: 'France'
};

# comma operator
const countries = Object.keys(cities).reduce((acc, k) => (acc[cities[k]] = [...(acc[cities[k]] || []), k], acc), {});

# return
const countries = Object.keys(cities).reduce((acc, k) => {
  let country = cities[k];
  acc[country] = [...(acc[country] || []), k];
  return acc;
}, {});

problem

/* befor */
[
  {
      name: '소나타',
      brand: '현대'
   },
   {
      name: '아반떼', 
      brand: '현대'
   },
   {
      name: 'K7',
      brand: '기아'
    }
]

/* after */
[
  {
    name: '소나타' or '아반떼',
    brand: '현대'
   },
   {
    name: 'K7',
    brand: '기아'
   }
]

solution

const func = (arr) => {
  return Object.values(arr.reduce((prev, cur) => Object.assign(prev, { [cur.brand]: cur }), {}));
}

const func = (arr) => {
  let uniq = {};
  return arr.filter(fil => !uniq[fil.brand] && (uniq[fil.brand] = true));
}

const func = (arr) => {
  return arr.filter((item, i) => array.findIndex((item2) => item['brand'] === item2['brand']) === i);
}

const func = (arr) => {
   let tempArray = [], resultArray = [];

  for(let i = 0; i < arr.length; i++) {
    let item = arr[i];

    if(tempArray.includes(item['brand'])) {
      continue;
    } else {
      resultArray.push(item);
      tempArray.push(item['brand']);
    }
  }

  return resultArray;
}

const func = (arr) => {
  return arr.reduce((prev, cur) => {
  if (!prev.some(obj => obj['brand'] !== cur['brand'])) {
      prev.push(cur);
  }
    return prev;
  }, []);
}

  • JSON 안의 특정 Key 값을 기준으로 값을 합치는 방법
  • ref 기준으로 값이 같으면 price 값을 합치는 결과를 만드는 방법

problem

/* befor */
[
  { ref: 'A', name: '바나나', price: 2 }, 
  { ref: 'B', name: '토마토', price: 20 }, 
  { ref: 'C', name: '수박', price: 23 }, 
  { ref: 'A', name: '바나나', price: 23 }
]

/* after */
[
   { ref: 'A', name: '바나나', price: 25 },
   { ref: 'B', name: '토마토', price: 20 },
   { ref: 'C', name: '수박', price: 23 }
]

solution

const unique = (items) => {
  const uniqued = items.reduce((acc, curr) => {
      const { ref, name, price } = curr;
      const prev = acc[ref];
      
      if (!prev) {
        return {
          ...acc,
          [ref]: { price, name },
        }
      }
      
      return {
        ...acc,
        [ref]: { name, price: Number(prev.price + price) }
      }
    }, {});
    
/** 
  * @Functions {Object.entries}
  * @Desc 객체 자체의 enumerable 속성 [key, value] 쌍의 배열을 반환합니다.
  */
  return Object.entries(uniqued).map(([ref, { name, price }]) => ({ ref, name, price }))
}

unique(prev);
  • 이중 객체에서 closed가 true것만 고르시오

problem

/* before */
{
  dsdb : {
    name: '대시보드',
    closed: false
  },
  mngt : {
    name: '관리',
    closed: true
  },
  pccr : {
    name: '정책',
    closed: true
  }
}

/* after */
{
  mngt : {
    name: '관리',
    closed: true
  },
  pccr : {
    name: '정책',
    closed: true
  }
}

solution

const result = Object.entries(data).filter(([key, value]) => value.closed).reduce((acc, [key, value]) => {
  acc[key] = value;
  return acc;
}, {});
  • 주어진 데이터에 따라 필터 구조를 만드시오
  • filtres 개가 2개 이상이면 logic 'or'를 추가한다.

problem

Input :
status = 1;
list = ['a', 'ㄱ'];

Output: 
[
 {
  filters: [
   {
    field: 'status',
    operator: 'eq',
    value: 1
   }
  ],
  logic: 'or'
 },
 {
  filters: [
   {
    field: 'list',
    operator: 'eq',
    value: 'a'
   },
   {
    field: 'list',
    operator: 'eq',
    value: 'ㄱ'
   }
  ],
  logic: 'or'
 }
]

solution

const status = 1;
const list = ['a', 'ㄱ'];

const filters = (data) => {
  if (typeof data !== 'object') return ;
  
  const createFilter = (field, operator, value) => {
    return { field, operator, value };
  }
  
  return Object.entries(data).map(([key, value], idx, arr) => {
    let filters = [];
    
    if (Array.isArray(value)) {
      filters = value.map(v => createFilter(key, 'eq', v));
    } else {
      filters.push(createFilter(key, 'eq', value));
    }
    
    let result = { filters };
    
    if (arr.length > 1) {
      result['logic'] = 'or';
    }
    
    return result;
  }).filter(v => v.filters.length);
}

filters(status, list);

if/Tertiary

const isWeekend = (day) => {
  let message;
  if (day === 'sunday') {
    message = 'Its a weekend';
  }
  
  return message;
}

message 초기값 선언을 하여 예외 처리를 확실하게 해준다.

const isWeekend = (day) => {
  let message = 'Its a working day :(';
  if (day === 'sunday') {
    message = 'Its a weekend';
  }
  
  return message;
}

삼항 연산자를 사용하여 코드를 좀 더 간결하게 수정한다.

const isWeekend = (day) => day === 'sunday' ? 'Its a weekend' : 'Its a working day :(';

or

// `(백틱) 템플릿 기능을 사용하여 간결하게 표현
const isWeekend = (day) => `Its a ${day === 'sunday' ? 'a weekend' : 'a working day :('}`;

if/Switch

switch (day) {
    case 'monday':
    case 'tuesday':
    case 'wednesday':
    case 'thursday':
    case 'friday':
        return 'Its a working day :(';
        break;
    case 'saturday':
    case 'sunday':
        return 'Its a weekend';
        break;
    default:
        return 'thats not even a day';
        break;
}

일반 객체와 nullish(null 또는 undefined) 연산자를 사용할 수 있다.

const daysMap = (day) =>
  ({
    "monday": "Its a working day :(",
    "tueday": "Its a working day :(",
    "wednesday": "Its a working day :(",
    "thursday": "Its a working day :(",
    "friday": "Its a working day :(",
    "saturday": "its a weekend",
    "sunday": "its a weekend",
  }[day] ?? "thats not even a day");

const isWeekend = (day) => daysMap(day);
  • 재귀함수를 사용하여 id가 같은 데이터들의 묶음 배열을 만들고 싶다.

problem

/* befor */
[
  { id: 1, name: 'a' },
  { id: 1, name: 'b' },
  { id: 2, name: 'c' },
  { id: 3, name: 'd' },
  { id: 2, name: 'e' }
]

/* after */
[
  [
    { id: 1, name: 'a' },
    { id: 1, name: 'b' }
  ],
  [
    { id: 2, name: 'c' },
    { id: 2, name: 'e' },
  ],
  [
    { id: 3, name: 'd' }
  ]
]

solution

let result = []; // 데이터들을 묶을 새 배열
let restLength = rest.length - 1; // 데이터 길이
let i = 0; // 반복문 인덱스

const loop = () => {
  if (result.length === 0) { // 새 배열의 데이터가 있는지 판별
    result.push([rest[0]]); // 없을 경우 데이터 삽입
  }

  if (i > 0) { // 반복문 인덱스가 0보다 클경우 즉, 데이터가 있을경우
    const resultIndex = result.findIndex((r) => { // 주어진 판별 함수를 만족하는 배열의 첫 번째 요소에 대한 인덱스 반환
      if (r) { // 데이터가 존재할 경우
        const [data] = r; // r의 경우 [{...}] 형식이라 []안에 감싼 변수로 초기값 선언
	return data.id === rest[i].id; // r의 데이터와 rest[i](데이터[인덱스]) 아이디가 같으면 해당 인덱스 반환
      }
      return false; // 데이터가 없으면 false 반환
    });
                
    if (resultIndex >= 0) { // 반환된 인덱스가 0보다 크면 즉, 존재하면 없으면 -1이다.
      result[resultIndex].push(rest[i]); // 해당 인덱스 번째의 배열 방에 해당 rest[i] 데이터 삽입
    }
    
    if (resultIndex === -1) { // 반환된 인덱스가 없을 경우, 즉 같은 아이디가 `id` 존재하지 않을경우 
      result.push([rest[i]]); // 배열 뒷부분에 rest[i] 삽입
    }
  }

  if (i < restLength) { // i가 데이터 길이보다 작을경우 즉, 반복문을 더 돌겟다는 의미
    i++; // i(인덱스) 값을 증가
    loop(); // 재귀함수로 다시 해당 함수를 불러온다.
  }
};

loop(); // 첫 함수 호출
  • 다음 데이터에서 count가 null일경우 하위 노드를 탐색하여 그 count의 합계로 변경하여라

problem

const orderList = [
  {
    id: 1,
    name: "김아무개",
    childnode: [
      {
        type: "상의",
        count: null,
        childnode: [
          {
            name: "블라우스",
            count: 20,
            price: 5000
          },
          {
            name: "가디건",
            count: 10,
            price: 12000
          }
        ]
      }
    ]
  },
  {
    id: 2,
    name: "홍길동",
    childnode: [
      {
        type: "악세서리",
        count: 100,
        childnode: []
      }
    ]
  }
];

solution (function)

const calc = () => {
  let productCopy = [...orderList]; // 전개 연산자 사용 해당 데이터를 대입

  productCopy.forEach((p) => { // forEach 배열을 순환
    p.childnode.forEach((s) => { // 순환하는 배열요소에서 childnode를 한번더 forEach 배열 순환
      let count = s.count; // s.count를 count 변수에 대입
      s.childnode.forEach(child => count += child.count); // s.childnode 요소를 forEach 배열 순환하여 count 변수에 요소 count 합
      s.count = count; // count 합을 s.count 대입
    });
  });
  
  return productCopy; // 결과 리턴
};

calc(); // 함수 호출

solution (recursion)

function fixNullCount(node, index = 0) {
  if (index >= node.length) {
    return;
  }

  if (node[index].count === null) {
    // childnode들의 count 총합은 귀찮으니까 걍 reduce 이용해서 shallow 하게 계산.
    node[index].count = node[index].childnode.reduce(
      (acc, curr) => (curr.count ? acc + curr.count : acc),
      0
    );
  }

  // childnode가 있으면 childnode 먼저 처리.
  if (node[index].childnode) {
    fixNullCount(node[index].childnode, 0);
  }

  // 다음 노드 처리.
  fixNullCount(node, index + 1);
  return node;
}

fixNullCount(orderList, 0);
  • DATE 형식을 가공하시오

problem

Input: '2020-01-1'
Output: '2020-01-01'

Input: '2020-3-30'
Output: '2020-03-30'

Input: '2020-8-8'
Output: '2020-08-08'

solution

const padDate = (n) => {
  return (str) => {
    while (str.length < n) {
      str = '0' + str;
    }
    return str;
  }
}

'2020-1-1'.split(/-/g).map(padDate(2)).join('-');
  • 재귀함수를 사용하여 type가 sk인 사람들의 name과 phone의 배열을 생성하시오.

problem

/* befor */
[
  {
    id: 1,
    name: "robert",
    phone: "010-2786-9902",
    type: "sk",
    childnode: [
      {
        id: 11,
        name: "echo",
        phone: "010-3923-1333",
        type: "kt",
        childnode: [
          {
            id: 115,
            name: "hary",
            phone: "010-2786-9302",
            type: "sk",
            childnode: [
              {
                id: 1159,
                name: "pobi",
                phone: "010-9302-0009",
                type: "kt",
                childnode: [
                  {
                    id: 11592,
                    name: "cherry",
                    phone: "010-1223-9932",
                    type: "lg",
                    childnode: []
                  },
                  {
                    id: 11595,
                    name: "solvin",
                    phone: "010-534-7843",
                    type: "sk",
                    childnode: []
                  }
                ]
              }
            ]
          },
          {
            id: 116,
            name: "kim",
            phone: "010-3796-1102",
            type: "kt",
            childnode: [
              {
                id: 1168,
                name: "hani",
                phone: "010-1223-6713",
                type: "sk",
                childnode: [
                  {
                    id: 11689,
                    name: "ho",
                    phone: "010-4434-4534",
                    type: "kt",
                    childnode: [
                      {
                        id: 116890,
                        name: "wonsuk",
                        phone: "010-3434-1302",
                        type: "kt",
                        childnode: []
                      },
                      {
                        id: 1168901,
                        name: "chulsu",
                        phone: "010-3100-9841",
                        type: "sk",
                        childnode: []
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            id: 117,
            name: "hong",
            phone: "010-2786-9902",
            type: "lg",
            childnode: []
          }
        ]
      }
    ]
  }
];

/* after */
[ 
  { name: 'robert', phone: '010-2786-9902' },
  { name: 'hary', phone: '010-2786-9302' },
  { name: 'solvin', phone: '010-534-7843' },
  { name: 'hani', phone: '010-1223-6713' },
  { name: 'chulsu', phone: '010-3100-9841' } 
]

solution

const findTypeUser = (arr) => {
  const array = []; // 데이터를 저장할 새 배열

  const findType = (arr) => { // 재귀 함수
    arr.forEach((element) => { // 반복문을 통하여 요소를 탐색한다.
      const { name, phone } = element; // 요소의 name, phone 데이터 선언
      if (element.type === "sk") array.push({ name, phone }); // 요소의 type가 sk이면 배열에 push
      findType(element.childnode); // childnode 배열로 재귀
    });
  }

  findType(arr); // 첫 재귀함수 호출
  return array; // 배열 반환
}

findTypeUser(newinput);
  • arr(obj), arr를 비교해서 arr(obj) id 값이 arr 존재할경우 selected: true로 반환하시오.

problem

/* before */
[
  {
    id: 'a',
    name: 'a'
  },
  {
    id: 'b',
    name: 'b'
  },
  {
    id: 'c',
    name: 'c'
  }
]

['b','c']

/* after */
[
  {
    id: 'a',
    name: 'a'
  },
  {
    id: 'b',
    name: 'b',
    checked: true
  },
  {
    id: 'c',
    name: 'c',
    checked: true
  }
]

solution

const results = obj.map(o => {
  if (arr.some(a => o.id === a)) {
    return { id: o.id, name: o.name, checked: true };
  }
  return { id: o.id, name: o.name };
});
  • 효율적인 switch 문법 사용 방법
const job = 'figure'
const [ lastName, firstName ] = ((job) => {
  switch (name) {
    case 'figure': return ['Kim', 'Yeon Ah'];
    case 'soccer': return ['Son', 'Heung Min'];
    case 'baseball': return ['Park', 'Chan Ho'];
  }
})(job);

console.log(lastName, firstName);

Output: Kim Yeon Ah
  • n명 플레이어가 있으면, 가능한 모든 가위 바위 보 경우를 모두 반환하시오.

problem

Input: 2
Output: 
[ 
  [ '가위', '가위' ],
  [ '가위', '바위' ],
  [ '가위', '보' ],
  [ '바위', '가위' ],
  [ '바위', '바위' ],
  [ '바위', '보' ],
  [ '보', '가위' ],
  [ '보', '바위' ],
  [ '보', '보' ] 
]

solution

const permutations = players => {
  const choices = ['가위', '바위', '보']; // 가위 바위 보 배열
  let result = []; // 경우의 수를 저장하는 새 배열

  const innerFunc = (player, choice) => { // 재귀함수
    if (player === players) { // 마지막 플레이어인지 검사
        result.push(choice.slice()); // 마지막일 경우 경우의 수에 저장
        return;
    } else {
      for (let i = 0; i < choices.length; i++) { // 가위 바위 보 배열을 순환
        choice.push(choices[i]); // 가위 바위 보 순서에 맞게 해당 값을 선택 배열에 저장
        innerFunc(player + 1, choice); // 현재 플레이가 마지막인지 검사 + 가위, 바위, 보 저장
        choice.pop(); // 마지막 플레이어 경우의 수를 변경하기 위해 제거
      }
    }
  };

  innerFunc(0, []); // 첫 재귀함수 호출
  return result; // 결과값 반환
};

permutations(2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment