@@ -100,6 +100,111 @@ export function concatenateArraysInProperty(source: Jso, target: Jso, propertyKe
100100 } )
101101}
102102
103+ export function removeDuplicates < T > (
104+ array : T [ ] ,
105+ getUniqueKey : ( item : T ) => string | undefined ,
106+ onDuplicate ?: ( item : T , index : number , firstIndex : number ) => void
107+ ) : T [ ] {
108+ const seen = new Map < string , number > ( ) // key -> first index
109+
110+ for ( let i = 0 ; i < array . length ; i ++ ) {
111+ const item = array [ i ]
112+ const key = getUniqueKey ( item )
113+
114+ if ( key === undefined ) {
115+ continue // Skip items without valid keys
116+ }
117+
118+ const firstIndex = seen . get ( key )
119+ if ( firstIndex !== undefined ) {
120+ // Duplicate found
121+ onDuplicate ?.( item , i , firstIndex )
122+ delete array [ i ] // Create sparse array
123+ } else {
124+ seen . set ( key , i )
125+ }
126+ }
127+
128+ return array // Returns sparse array
129+ }
130+
131+ export function densify < T > ( sparseArray : T [ ] , originsFlag : symbol | undefined ) : T [ ] {
132+ const dense : T [ ] = [ ]
133+ const originsRecord : OriginsMetaRecord = { }
134+
135+ for ( let i = 0 ; i < sparseArray . length ; i ++ ) {
136+ if ( i in sparseArray ) { // Check if index exists (not deleted)
137+ const newIndex = dense . length
138+ dense [ newIndex ] = sparseArray [ i ]
139+
140+ // Copy origins if they exist
141+ if ( originsFlag ) {
142+ const sourceOrigins = resolveOrigins ( sparseArray , i , originsFlag )
143+ if ( sourceOrigins ) {
144+ originsRecord [ newIndex ] = sourceOrigins
145+ }
146+ }
147+ }
148+ }
149+
150+ // Set origins for the dense array
151+ if ( originsFlag && Object . keys ( originsRecord ) . length > 0 ) {
152+ setJsoProperty ( dense as any , originsFlag , originsRecord )
153+ }
154+
155+ return dense
156+ }
157+
158+ export function addUniqueElements (
159+ source : Jso ,
160+ target : Jso ,
161+ propertyKey : PropertyKey ,
162+ originsFlag : symbol | undefined ,
163+ getUniqueKey : ( item : any ) => string | undefined
164+ ) : void {
165+ const sourceArray = getJsoProperty ( source , propertyKey )
166+ if ( ! isArray ( sourceArray ) ) {
167+ return
168+ }
169+
170+ let targetArray = getJsoProperty ( target , propertyKey )
171+ if ( targetArray === undefined ) {
172+ targetArray = [ ]
173+ copyOrigins ( source , target , propertyKey , propertyKey , originsFlag )
174+ }
175+
176+ if ( ! isArray ( targetArray ) ) {
177+ return
178+ }
179+
180+ setJsoProperty ( target , propertyKey , targetArray )
181+
182+ // Build set of existing keys in target
183+ const existingKeys = new Set < string > ( )
184+ for ( const item of targetArray ) {
185+ const key = getUniqueKey ( item )
186+ if ( key !== undefined ) {
187+ existingKeys . add ( key )
188+ }
189+ }
190+
191+ // Add source items that don't exist in target
192+ for ( let i = 0 ; i < sourceArray . length ; i ++ ) {
193+ const item = sourceArray [ i ]
194+ const key = getUniqueKey ( item )
195+
196+ // Skip if already exists in target (operation overrides path) or key is undefined
197+ if ( key === undefined || existingKeys . has ( key ) ) {
198+ continue
199+ }
200+
201+ // Add to target
202+ const targetIndex = targetArray . length
203+ targetArray [ targetIndex ] = item
204+ copyOrigins ( sourceArray , targetArray , i , targetIndex , originsFlag )
205+ }
206+ }
207+
103208export function resolveOriginsMetaRecord ( source : Jso , originsFlag : symbol | undefined ) : OriginsMetaRecord | undefined {
104209 if ( ! originsFlag ) {
105210 return undefined
@@ -214,4 +319,4 @@ export function copyOriginsForArray(sourceArray: unknown[], targetArray: unknown
214319
215320export const createSelfOriginsCloneHook : < T extends HasSelfOriginsResolver , R extends { } > ( originsFlag : symbol | undefined ) => SyncCloneHook < T , R > = < State extends HasSelfOriginsResolver , Rules extends { } > ( originsFlag : symbol | undefined ) => {
216321 return createSelfMetaCloneHook < OriginLeafs , 'selfOriginResolver' , State , Rules > ( 'selfOriginResolver' , originsFlag , [ ] )
217- }
322+ }
0 commit comments