Skip to content

Commit df1345a

Browse files
[#2] size 함수 추가
1 parent fff6e99 commit df1345a

File tree

5 files changed

+183
-2
lines changed

5 files changed

+183
-2
lines changed

.github/workflows/detect-changed-packages.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
uses: NaverPayDev/changeset-actions/detect-add@main
3636
with:
3737
github_token: ${{ secrets.ACTION_TOKEN }}
38-
packages_dir: packages,share
38+
packages_dir: .
3939
skip_label: skip-detect-change
4040
skip_branches: main
4141
formatting_script: pnpm run markdownlint:fix

src/isEmpty.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {isArrayLike} from './internal'
22

3-
export default function isEmpty(value: unknown): boolean {
3+
export function isEmpty(value: unknown): boolean {
44
if (value == null) {
55
return true
66
}
@@ -26,3 +26,5 @@ export default function isEmpty(value: unknown): boolean {
2626

2727
return false
2828
}
29+
30+
export default isEmpty

src/size.bench.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import _size from 'lodash/size'
2+
import {bench, describe} from 'vitest'
3+
4+
import size from './size'
5+
6+
const testCases = [
7+
null,
8+
undefined,
9+
'',
10+
'hello',
11+
[],
12+
[1, 2, 3],
13+
{},
14+
{key: 'value'},
15+
new Map(),
16+
new Set(),
17+
new Map([
18+
['a', 1],
19+
['b', 2],
20+
]),
21+
new Set([1, 2, 3]),
22+
{a: 1, b: 2, c: 3},
23+
Array(1000).fill(0),
24+
'a'.repeat(1000),
25+
new Array(1000)
26+
.fill(0)
27+
.map((_, i) => [`key${i}`, i])
28+
.reduce((acc, [k, v]) => ({...acc, [k]: v}), {}),
29+
]
30+
31+
const ITERATIONS = 10000
32+
33+
describe('size', () => {
34+
bench('hidash', () => {
35+
for (let i = 0; i < ITERATIONS; i++) {
36+
testCases.forEach((testCase) => {
37+
size(testCase)
38+
})
39+
}
40+
})
41+
42+
bench('lodash', () => {
43+
for (let i = 0; i < ITERATIONS; i++) {
44+
testCases.forEach((testCase) => {
45+
size(testCase)
46+
})
47+
}
48+
})
49+
})

src/size.test.ts

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {describe, test, expect} from 'vitest'
2+
3+
import size from './size'
4+
5+
describe('size function', () => {
6+
test('returns 0 for null and undefined', () => {
7+
expect(size(null)).toBe(0)
8+
expect(size(undefined)).toBe(0)
9+
})
10+
11+
test('returns correct length for strings', () => {
12+
expect(size('')).toBe(0)
13+
expect(size('hello')).toBe(5)
14+
expect(size('한글')).toBe(2)
15+
})
16+
17+
test('returns correct length for arrays', () => {
18+
expect(size([])).toBe(0)
19+
expect(size([1, 2, 3])).toBe(3)
20+
expect(size(new Array(5))).toBe(5)
21+
})
22+
23+
test('returns correct size for objects', () => {
24+
expect(size({})).toBe(0)
25+
expect(size({a: 1, b: 2})).toBe(2)
26+
expect(size(Object.create(null))).toBe(0)
27+
})
28+
29+
test('returns correct size for Map', () => {
30+
expect(size(new Map())).toBe(0)
31+
const map = new Map([
32+
['a', 1],
33+
['b', 2],
34+
])
35+
expect(size(map)).toBe(2)
36+
})
37+
38+
test('returns correct size for Set', () => {
39+
expect(size(new Set())).toBe(0)
40+
const set = new Set([1, 2, 3])
41+
expect(size(set)).toBe(3)
42+
})
43+
44+
test('returns 0 for non-collection primitives', () => {
45+
expect(size(0)).toBe(0)
46+
expect(size(42)).toBe(0)
47+
expect(size(true)).toBe(0)
48+
expect(size(false)).toBe(0)
49+
expect(size(Symbol('TEST'))).toBe(0)
50+
})
51+
52+
test('returns correct length for array-like objects', () => {
53+
const arrayLike = {length: 3, 0: 'a', 1: 'b', 2: 'c'}
54+
expect(size(arrayLike)).toBe(3)
55+
})
56+
57+
test('returns 0 for functions', () => {
58+
expect(size(() => {})).toBe(0)
59+
expect(size(function () {})).toBe(0)
60+
})
61+
62+
test('handles objects with inherited properties', () => {
63+
const proto = {inherited: true}
64+
const obj = Object.create(proto)
65+
obj.own = true
66+
expect(size(obj)).toBe(1)
67+
})
68+
69+
test('returns correct size for large collections', () => {
70+
const largeArray = Array(1000000).fill(0)
71+
expect(size(largeArray)).toBe(1000000)
72+
73+
const largeString = 'a'.repeat(1000000)
74+
expect(size(largeString)).toBe(1000000)
75+
76+
const largeObject: Record<string, number> = {}
77+
for (let i = 0; i < 10000; i++) {
78+
largeObject[`key${i}`] = i
79+
}
80+
expect(size(largeObject)).toBe(10000)
81+
})
82+
83+
// WeakMap, WeakSet은 사이즈를 알 방법이 없으므로 항상 0을 반환한다.
84+
test('returns 0 for WeakMap', () => {
85+
const weakMap = new WeakMap()
86+
const key1 = {}
87+
const key2 = {}
88+
weakMap.set(key1, 'value1')
89+
weakMap.set(key2, 'value2')
90+
expect(size(weakMap)).toBe(0)
91+
})
92+
93+
test('returns 0 for WeakSet', () => {
94+
const weakSet = new WeakSet()
95+
const obj1 = {}
96+
const obj2 = {}
97+
weakSet.add(obj1)
98+
weakSet.add(obj2)
99+
expect(size(weakSet)).toBe(0)
100+
})
101+
102+
test('returns 0 for WeakMap and WeakSet even with elements', () => {
103+
const weakMap = new WeakMap([[{}, 'value']])
104+
const weakSet = new WeakSet([{}])
105+
expect(size(weakMap)).toBe(0)
106+
expect(size(weakSet)).toBe(0)
107+
})
108+
})

src/size.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {isArrayLike} from './internal'
2+
3+
export function size(collection: unknown): number {
4+
if (collection == null) {
5+
return 0
6+
}
7+
if (isArrayLike(collection)) {
8+
return collection.length
9+
}
10+
11+
const type = Object.prototype.toString.call(collection)
12+
if (type === '[object Map]' || type === '[object Set]') {
13+
return (collection as Map<unknown, unknown> | Set<unknown>).size
14+
}
15+
16+
if (typeof collection === 'object') {
17+
return Object.keys(collection as object).length
18+
}
19+
return 0
20+
}
21+
22+
export default size

0 commit comments

Comments
 (0)