@@ -1870,3 +1870,76 @@ func CrossJoinByErr9[A, B, C, D, E, F, G, H, I, Out any](listA []A, listB []B, l
18701870
18711871 return result , nil
18721872}
1873+
1874+ // NestJoin executes a condition join (Theta Join) between two slices using a
1875+ // Nested Loop Join algorithm.
1876+ //
1877+ // It iterates through every element in the 'left' slice and compares it with
1878+ // every element in the 'right' slice using the provided 'match' predicate.
1879+ // If 'match' returns true, the 'mapper' function is invoked to combine the two
1880+ // elements into a single result of type 'R'.
1881+ //
1882+ // Since it evaluates all possible pairs, it supports arbitrary matching criteria
1883+ // (e.g., inequalities, regex, or complex logical conditions).
1884+ //
1885+ // Time Complexity: O(N * M), where N is len(left) and M is len(right).
1886+ // Space Complexity: O(1) beyond the memory required for the resulting slice.
1887+ func NestJoin [J , K , R any ](
1888+ left []J ,
1889+ right []K ,
1890+ match func (J , K ) bool ,
1891+ mapper func (J , K ) R ,
1892+ ) []R {
1893+ var r []R
1894+
1895+ for _ , j := range left {
1896+ for _ , k := range right {
1897+ if ! match (j , k ) {
1898+ continue
1899+ }
1900+ r = append (r , mapper (j , k ))
1901+ }
1902+ }
1903+
1904+ return r
1905+ }
1906+
1907+ // LeftJoin performs a left outer join between two slices based on a common key.
1908+ //
1909+ // It builds a lookup table (map) from the 'right' slice using 'rk' to extract keys.
1910+ // Then, it iterates through the 'left' slice, retrieves the corresponding element
1911+ // from the map using the key extracted by 'lk', and projects the result using 'mapper'.
1912+ //
1913+ // Behavior Notes:
1914+ // - If multiple elements in 'right' share the same key, 'KeyBy' will overwrite
1915+ // previous values, keeping only the last one.
1916+ // - If a key from the 'left' slice does not exist in 'right', the 'mapper'
1917+ // is still called, passing the zero value of type 'RE' for the right side.
1918+ // - The length of the returned slice is always equal to len(left).
1919+ //
1920+ // Time Complexity: O(N + M), where N is len(left) and M is len(right), leveraging
1921+ // hash-based lookup for optimal performance with large datasets.
1922+ // Space Complexity: O(M) to store the intermediate lookup map for the right slice.
1923+ func LeftJoin [K comparable , LE , RE , R any ](
1924+ left []LE ,
1925+ right []RE ,
1926+ lk func (item LE ) K ,
1927+ rk func (item RE ) K ,
1928+ mapper func (LE , RE ) R ,
1929+ ) []R {
1930+ if len (left ) == 0 {
1931+ return nil
1932+ }
1933+
1934+ var r = make ([]R , 0 , len (left ))
1935+
1936+ rm := KeyBy (right , rk )
1937+
1938+ for _ , j := range left {
1939+ k := lk (j )
1940+ re := rm [k ]
1941+ r = append (r , mapper (j , re ))
1942+ }
1943+
1944+ return r
1945+ }
0 commit comments