상권's
TIL 23 (2021.10.29) 본문
2021.10.29 오늘의 코플릿
문자열을 입력받아 문자열 내의 모든 괄호의 짝이 맞는지 여부를 리턴해야 합니다.
다음 단계에 맞춰 함수를 작성해 보세요
괄호의 종류를 단 한가지로 한정합니다.
괄호의 종류를 늘려 모든 종류의 괄호에도 작동하도록 합니다.
괄호를 제외한 문자열이 포함된 경우에도 작동하도록 합니다.
// str.split('') 해서 배열로 만들어준다.
// 앞에서 하나씩 빼면서 (, ) 가 맞다면 각각 다른 배열에 넣어준다.
// 두 배열의 길이가 맞다면 true를 리턴한다. => )( 이렇게 입력되는 경우에도 true가 뜬다...
// 절반으로 나눠서 진행하는 건 어렵다... => stack 처럼 진행을 한다.
첫 수도코드 => 처음에는 괄호들이 (, ) 이렇게 들어오든, ), ( 이렇게 들어오든 짝은 맞으니깐 통과가 될 줄 알고, 수도코드처럼 코드를 구현해봤습니다. 근데, ), ( 의 경우에는 테스트 통과가 안되었습니다. 결국 구글링을 통해서 코드를 구현하게 되었습니다.
const balancedBrackets = function (str) {
let brackets = { "(": ")", "{":"}", "[":"]" }
let arr = str.split('')
let result = arr.reduce(function(acc, cur) {
if(cur === brackets[acc[acc.length - 1]]) {
acc.pop()
}
else {
acc.push(cur)
}
return acc
}, [])
return result.length === 0
}
brackets 객체에다가 괄호 별로 키와 벨류를 지정해줍니다. => 인자로 받는 문자열을 split을 통해서 배열로 만들어 줍니다. => 제일 첫번째 값은 acc에 push를 해줍니다. => 그 다음에 나오는 부분이 금방 들어갔던 값의 벨류에 해당하면 금방 들어갔던 값을 acc에서 pop해줍니다( 스택으로 LIFO 적용 ) => 아니라면 acc 추가합니다.(반복) => 모든 것이 짝이 맞다면 result의 length는 0이 됩니다. 짝인 안 맞으면 length는 0이 아닙니다.
레프런스 코드도 확인을 했는데, 해당 방법이 더 간단하고 직관성이 있는 거 같습니다. 이러한 문제가 또 나온다면, 스택과 객체를 이용해서 풀 수 있도록 노력하겠습니다.
목, 금요일에 학습했던 CSS와 더불어서 React에서 모달, 토글, 탭, 태그 기능 구현했습니다. state, props 는 익숙해졌는데, styled-component 구현이 생각대로 되지 않아 css 비중이 작았던 탭과 태그에 대해서 먼저 올리고, 모달과 토글의 css에 대해서 학습한 후 이해가 되면 그때 올리도록 하겠습니다.
처음 storybook을 이용해봤는데, 사용법이 익숙하지 않지만, 해당 컴포넌트만 보여주기 때문에 작업하기 편리했습니다. 나머지 기능 css에 대해서 학습하면서 사용 방법을 익혀야겠습니다.
태그 기능.

export const TagsInput = styled.div`
margin: 8rem auto;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
min-height: 48px;
width: 480px;
padding: 0 8px;
border: 1px solid rgb(214, 216, 218);
border-radius: 6px;
> ul {
display: flex;
flex-wrap: wrap;
padding: 0;
margin: 8px 0 0 0;
> .tag {
width: auto;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
padding: 0 8px;
font-size: 14px;
list-style: none;
border-radius: 6px;
margin: 0 8px 8px 0;
background: #4000c7;
> .tag-close-icon {
display: block;
width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
font-size: 14px;
margin-left: 8px;
color: #4000c7;
border-radius: 50%;
background: #fff;
cursor: pointer;
}
}
}
> input {
flex: 1;
border: none;
height: 46px;
font-size: 14px;
padding: 4px 0 0 0;
:focus {
outline: transparent;
}
}
&:focus-within {
border: 1px solid #4000c7;
}
`;
export const Tag = () => {
const initialTags = ['CodeStates', 'kimcoding'];
const [tags, setTags] = useState(initialTags);
const removeTags = (indexToRemove) => {
let targetValue = tags.indexOf(indexToRemove.tag)
// onClick이 작동이 된 태그의 인덱스를 찾는다.
let removedArr = [...tags]
removedArr.splice(targetValue, 1)
//splice를 사용해서 해당 값을 tags에서 없앤다.
setTags(removedArr)
};
const addTags = (event) => {
if (event.code === 'Enter') {
if (event.target.value === '') {
return ''
} // input에서 입력되는 값이 문자, 숫자는 태그를 작성하는 것이고,
// enter가 눌러진다면, 태그를 추가한다.
// 입력된 값이 없는데 enter가 눌러진다면 아무 일도 일어나지 않는다.
else {
if(tags.includes(event.target.value) === false) {
const newTags = [...tags]
newTags.push(event.target.value)
setTags(newTags)
event.target.value = ''
}
// 입력된 값이랑 기존에 있던 값이 같다면 추가되지 않으며,
// 동일한 값이 없다면 태그에 추가되고, input은 빈칸이 된다.
else {
return ''
}
}
}
}
return (
<>
<TagsInput>
<ul id='tags'>
{tags.map((tag, index) => (
<li key={index} className='tag'>
<span className='tag-title'>{tag}</span>
<span className='tag-close-icon' onClick={({tag}) => removeTags({tag})}> X
</span>
</li>
))}
</ul>
<input
className='tag-input'
type='text'
onKeyUp={(value)=> addTags(value)}
placeholder='Press enter to add tags'
/>
</TagsInput>
</>
);
};
탭 기능.

const TabMenu = styled.ul`
background-color: #dcdcdc;
color: rgba(73, 73, 73, 0.5);
font-weight: bold;
display: flex;
flex-direction: row;
justify-items: center;
align-items: center;
list-style: none;
margin-bottom: 7rem;
.submenu {
// 기존적인 태그들에 적용될 css
padding-left: 10px;
padding-right: 50px;
border-color: black;
}
.focused {
// 클릭이 되는 태그에 적용될 css
background-color: red;
}
& div.desc {
text-align: center;
}
`;
const Desc = styled.div`
text-align: center;
`;
export const Tab = () => {
const [currentTab, setCurrentTab] = useState(0)
// 클릭이 되는 tag에 맞춰서 하단에 위치한 content가 변경되기 위해 state로 설정
const menuArr = [
{ name: 'Tab1', content: 'Tab menu ONE' },
{ name: 'Tab2', content: 'Tab menu TWO' },
{ name: 'Tab3', content: 'Tab menu THREE' },
];
const selectMenuHandler = (index) => {
setCurrentTab(index)
// map을 통해서 index 나오고, 클릭되는 tag의 index를 파라미터로 받아서
// currentTab를 바꾼다.
};
return (
<>
<div>
<TabMenu>
{menuArr.map((el, i) => {
return (
<li className={`submenu${currentTab === i ? " focused" : ""}`} key={i} onClick={() => selectMenuHandler(i)}>{menuArr[i].name}</li>
) // currentTab과 index가 같다면, focused class가 적용이되고, 나머지는 sunmenu만 적용된다.
})}
</TabMenu>
<Desc>
<p>{menuArr[currentTab].content}</p>
</Desc>
</div>
</>
);
};
'~2022 작성 글 > TIL' 카테고리의 다른 글
TIL 25 (2021.10.31) (0) | 2021.10.31 |
---|---|
TIL 24 (클로저 함수)(2021.10.30) (0) | 2021.10.30 |
TIL 22 (2021.10.28) (0) | 2021.10.28 |
TIL 21 (storybook, CSS방법론, styled-component, Ref)(2021.10.27) (0) | 2021.10.27 |
TIL 20 (express.js, 미들웨어, 디버깅, location header)(2021.10.26) (0) | 2021.10.26 |