[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-4798":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":23,"hasPages":23,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":37,"readmeContent":38,"aiSummary":39,"trendingCount":16,"starSnapshotCount":16,"syncStatus":40,"lastSyncTime":41,"discoverSource":42},4798,"lo","samber\u002Flo","samber","💥  A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)","https:\u002F\u002Flo.samber.dev",null,"Go",21325,945,75,121,0,3,13,68,14,43.93,"MIT License",false,"master",[26,27,28,29,30,31,32,33,34,35,36],"constraints","contract","filterable","foldable","functional","generics","go","golang","lodash","programming","typesafe","2026-06-12 02:01:04","\n# lo - Iterate over slices, maps, channels...\n\n[![tag](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Ftag\u002Fsamber\u002Flo.svg)](https:\u002F\u002Fgithub.com\u002Fsamber\u002Flo\u002Freleases)\n![Go Version](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FGo-%3E%3D%201.18-%23007d9c)\n[![GoDoc](https:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fsamber\u002Flo?status.svg)](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fsamber\u002Flo)\n![Build Status](https:\u002F\u002Fgithub.com\u002Fsamber\u002Flo\u002Factions\u002Fworkflows\u002Ftest.yml\u002Fbadge.svg)\n[![Go report](https:\u002F\u002Fgoreportcard.com\u002Fbadge\u002Fgithub.com\u002Fsamber\u002Flo)](https:\u002F\u002Fgoreportcard.com\u002Freport\u002Fgithub.com\u002Fsamber\u002Flo)\n[![Coverage](https:\u002F\u002Fimg.shields.io\u002Fcodecov\u002Fc\u002Fgithub\u002Fsamber\u002Flo)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fsamber\u002Flo)\n[![Contributors](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fcontributors\u002Fsamber\u002Flo)](https:\u002F\u002Fgithub.com\u002Fsamber\u002Flo\u002Fgraphs\u002Fcontributors)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Fsamber\u002Flo)](.\u002FLICENSE)\n\n✨ **`samber\u002Flo` is a Lodash-style Go library based on Go 1.18+ Generics.**\n\nA utility library based on Go 1.18+ generics that makes it easier to work with slices, maps, strings, channels, and functions. It provides dozens of handy methods to simplify common coding tasks and improve code readability. It may look like [Lodash](https:\u002F\u002Fgithub.com\u002Flodash\u002Flodash) in some aspects.\n\n5 to 10 helpers may overlap with those from the Go standard library, in packages `slices` and `maps`. I feel this library is legitimate and offers many more valuable abstractions.\n\n**See also:**\n\n- [samber\u002Fro](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fro): Reactive Programming for Go: declarative and composable API for event-driven applications\n- [samber\u002Fdo](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fdo): A dependency injection toolkit based on Go 1.18+ Generics\n- [samber\u002Fmo](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fmo): Monads based on Go 1.18+ Generics (Option, Result, Either...)\n- [samber\u002Fcc-skills-golang](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang): AI Agent Skills for Golang\n\nWhat makes it different from **samber\u002Fro**?\n- lo: synchronous helpers across finite sequences (maps, slices...)\n- ro: processing of infinite data streams for event-driven scenarios\n\n----\n\n\u003Cdiv align=\"center\">\n  \u003Csup>\u003Cb>💖 Sponsored by:\u003C\u002Fb>\u003C\u002Fsup>\n  \u003Cbr>\n  \u003Ca href=\"https:\u002F\u002Fwww.dbos.dev\u002F?utm_campaign=gh-smbr\">\n    \u003Cdiv>\n\t  \u003Cimg width=\"200\" alt=\"dbos\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd583cb62-7735-4d3c-beb7-e6ef1a5faf49\" \u002F>\n    \u003C\u002Fdiv>\n    \u003Cdiv>\n      DBOS - Durable workflow orchestration library for Go\n    \u003C\u002Fdiv>\n  \u003C\u002Fa>\n\u003C\u002Fdiv>\n\n----\n\n**Why this name?**\n\nI wanted a **short name**, similar to \"Lodash\", and no Go package uses this name.\n\n![lo](docs\u002Fstatic\u002Fimg\u002Flogo-full.png)\n\n## 🚀 Install\n\n```sh\ngo get github.com\u002Fsamber\u002Flo@v1\n\n# AI Agent Skill\nnpx skills add https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang --skill golang-samber-lo\n```\n\nThis library is v1 and follows SemVer strictly.\n\nNo breaking changes will be made to exported APIs before v2.0.0, except for experimental packages under `exp\u002F`.\n\nThis library has no dependencies outside the Go standard library.\n\n## 💡 Usage\n\nYou can import `lo` using:\n\n```go\nimport (\n    \"github.com\u002Fsamber\u002Flo\"\n    lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n    lom \"github.com\u002Fsamber\u002Flo\u002Fmutable\"\n    loi \"github.com\u002Fsamber\u002Flo\u002Fit\"\n)\n```\n\nThen use one of the helpers below:\n\n```go\nnames := lo.Uniq([]string{\"Samuel\", \"John\", \"Samuel\"})\n\u002F\u002F []string{\"Samuel\", \"John\"}\n```\n\n### Tips for lazy developers\n\nI cannot recommend it, but in case you are too lazy for repeating `lo.` everywhere, you can import the entire library into the namespace.\n\n```go\nimport (\n    . \"github.com\u002Fsamber\u002Flo\"\n)\n```\n\nI take no responsibility for this junk. 😁 💩\n\n## 🤠 Spec\n\nGoDoc: [godoc.org\u002Fgithub.com\u002Fsamber\u002Flo](https:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fsamber\u002Flo)\n\nDocumentation: [lo.samber.dev](https:\u002F\u002Flo.samber.dev\u002Fdocs\u002Fabout)\n\nSupported helpers for slices:\n\n- [Filter](#filter)\n- [Map](#map)\n- [UniqMap](#uniqmap)\n- [FilterMap](#filtermap)\n- [FlatMap](#flatmap)\n- [Reduce](#reduce)\n- [ReduceRight](#reduceright)\n- [ForEach](#foreach)\n- [ForEachWhile](#foreachwhile)\n- [Times](#times)\n- [Uniq](#uniq)\n- [UniqBy](#uniqby)\n- [GroupBy](#groupby)\n- [GroupByMap](#groupbymap)\n- [Chunk](#chunk)\n- [Window](#window)\n- [Sliding](#sliding)\n- [PartitionBy](#partitionby)\n- [Flatten](#flatten)\n- [Concat](#concat)\n- [Interleave](#interleave)\n- [Shuffle](#shuffle)\n- [Reverse](#reverse)\n- [Fill](#fill)\n- [Repeat](#repeat)\n- [RepeatBy](#repeatby)\n- [KeyBy](#keyby)\n- [SliceToMap \u002F Associate](#slicetomap-alias-associate)\n- [FilterSliceToMap](#filterslicetomap)\n- [Keyify](#keyify)\n- [Take](#take)\n- [TakeWhile](#takewhile)\n- [TakeFilter](#takefilter)\n- [Drop](#drop)\n- [DropRight](#dropright)\n- [DropWhile](#dropwhile)\n- [DropRightWhile](#droprightwhile)\n- [DropByIndex](#DropByIndex)\n- [Reject](#reject)\n- [RejectMap](#rejectmap)\n- [FilterReject](#filterreject)\n- [Count](#count)\n- [CountBy](#countby)\n- [CountValues](#countvalues)\n- [CountValuesBy](#countvaluesby)\n- [Subset](#subset)\n- [Slice](#slice)\n- [Replace](#replace)\n- [ReplaceAll](#replaceall)\n- [Clone](#clone)\n- [Compact](#compact)\n- [IsSorted](#issorted)\n- [IsSortedBy](#issortedby)\n- [Splice](#Splice)\n- [Cut](#Cut)\n- [CutPrefix](#CutPrefix)\n- [CutSuffix](#CutSuffix)\n- [Trim](#Trim)\n- [TrimLeft](#TrimLeft)\n- [TrimPrefix](#TrimPrefix)\n- [TrimRight](#TrimRight)\n- [TrimSuffix](#TrimSuffix)\n\nSupported helpers for maps:\n\n- [Keys](#keys)\n- [UniqKeys](#uniqkeys)\n- [HasKey](#haskey)\n- [ValueOr](#valueor)\n- [Values](#values)\n- [UniqValues](#uniqvalues)\n- [PickBy](#pickby)\n- [PickByKeys](#pickbykeys)\n- [PickByValues](#pickbyvalues)\n- [OmitBy](#omitby)\n- [OmitByKeys](#omitbykeys)\n- [OmitByValues](#omitbyvalues)\n- [Entries \u002F ToPairs](#entries-alias-topairs)\n- [FromEntries \u002F FromPairs](#fromentries-alias-frompairs)\n- [Invert](#invert)\n- [Assign (merge of maps)](#assign)\n- [ChunkEntries](#chunkentries)\n- [MapKeys](#mapkeys)\n- [MapValues](#mapvalues)\n- [MapEntries](#mapentries)\n- [MapToSlice](#maptoslice)\n- [FilterMapToSlice](#FilterMapToSlice)\n- [FilterKeys](#FilterKeys)\n- [FilterValues](#FilterValues)\n\nSupported math helpers:\n\n- [Range \u002F RangeFrom \u002F RangeWithSteps](#range--rangefrom--rangewithsteps)\n- [Clamp](#clamp)\n- [Sum](#sum)\n- [SumBy](#sumby)\n- [Product](#product)\n- [ProductBy](#productby)\n- [Mean](#mean)\n- [MeanBy](#meanby)\n- [Mode](#mode)\n\nSupported helpers for strings:\n\n- [RandomString](#randomstring)\n- [Substring](#substring)\n- [ChunkString](#chunkstring)\n- [RuneLength](#runelength)\n- [PascalCase](#pascalcase)\n- [CamelCase](#camelcase)\n- [KebabCase](#kebabcase)\n- [SnakeCase](#snakecase)\n- [Words](#words)\n- [Capitalize](#capitalize)\n- [Ellipsis](#ellipsis)\n\nSupported helpers for tuples:\n\n- [T2 -> T9](#t2---t9)\n- [Unpack2 -> Unpack9](#unpack2---unpack9)\n- [Zip2 -> Zip9](#zip2---zip9)\n- [ZipBy2 -> ZipBy9](#zipby2---zipby9)\n- [Unzip2 -> Unzip9](#unzip2---unzip9)\n- [UnzipBy2 -> UnzipBy9](#unzipby2---unzipby9)\n- [CrossJoin2 -> CrossJoin2](#crossjoin2---crossjoin9)\n- [CrossJoinBy2 -> CrossJoinBy2](#crossjoinby2---crossjoinby9)\n\nSupported helpers for time and duration:\n\n- [Duration](#duration)\n- [Duration0 -> Duration10](#duration0---duration10)\n\nSupported helpers for channels:\n\n- [ChannelDispatcher](#channeldispatcher)\n- [SliceToChannel](#slicetochannel)\n- [ChannelToSlice](#channeltoslice)\n- [Generator](#generator)\n- [Buffer](#buffer)\n- [BufferWithContext](#bufferwithcontext)\n- [BufferWithTimeout](#bufferwithtimeout)\n- [FanIn](#fanin)\n- [FanOut](#fanout)\n\nSupported intersection helpers:\n\n- [Contains](#contains)\n- [ContainsBy](#containsby)\n- [Every](#every)\n- [EveryBy](#everyby)\n- [Some](#some)\n- [SomeBy](#someby)\n- [None](#none)\n- [NoneBy](#noneby)\n- [Intersect](#intersect)\n- [IntersectBy](#intersectby)\n- [Difference](#difference)\n- [Union](#union)\n- [Without](#without)\n- [WithoutBy](#withoutby)\n- [WithoutEmpty](#withoutempty)\n- [WithoutNth](#withoutnth)\n- [ElementsMatch](#ElementsMatch)\n- [ElementsMatchBy](#ElementsMatchBy)\n\nSupported search helpers:\n\n- [IndexOf](#indexof)\n- [LastIndexOf](#lastindexof)\n- [HasPrefix](#hasprefix)\n- [HasSuffix](#hassuffix)\n- [Find](#find)\n- [FindIndexOf](#findindexof)\n- [FindLastIndexOf](#findlastindexof)\n- [FindOrElse](#findorelse)\n- [FindKey](#findkey)\n- [FindKeyBy](#findkeyby)\n- [FindUniques](#finduniques)\n- [FindUniquesBy](#finduniquesby)\n- [FindDuplicates](#findduplicates)\n- [FindDuplicatesBy](#findduplicatesby)\n- [Min](#min)\n- [MinIndex](#minindex)\n- [MinBy](#minby)\n- [MinIndexBy](#minindexby)\n- [Earliest](#earliest)\n- [EarliestBy](#earliestby)\n- [Max](#max)\n- [MaxIndex](#maxindex)\n- [MaxBy](#maxby)\n- [MaxIndexBy](#maxindexby)\n- [Latest](#latest)\n- [LatestBy](#latestby)\n- [First](#first)\n- [FirstOrEmpty](#FirstOrEmpty)\n- [FirstOr](#FirstOr)\n- [Last](#last)\n- [LastOrEmpty](#LastOrEmpty)\n- [LastOr](#LastOr)\n- [Nth](#nth)\n- [NthOr](#nthor)\n- [NthOrEmpty](#nthorempty)\n- [Sample](#sample)\n- [SampleBy](#sampleby)\n- [Samples](#samples)\n- [SamplesBy](#samplesby)\n\nConditional helpers:\n\n- [Ternary](#ternary)\n- [TernaryF](#ternaryf)\n- [If \u002F ElseIf \u002F Else](#if--elseif--else)\n- [Switch \u002F Case \u002F Default](#switch--case--default)\n\nType manipulation helpers:\n\n- [IsNil](#isnil)\n- [IsNotNil](#isnotnil)\n- [ToPtr](#toptr)\n- [Nil](#nil)\n- [EmptyableToPtr](#emptyabletoptr)\n- [FromPtr](#fromptr)\n- [FromPtrOr](#fromptror)\n- [ToSlicePtr](#tosliceptr)\n- [FromSlicePtr](#fromsliceptr)\n- [FromSlicePtrOr](#fromsliceptror)\n- [ToAnySlice](#toanyslice)\n- [FromAnySlice](#fromanyslice)\n- [Empty](#empty)\n- [IsEmpty](#isempty)\n- [IsNotEmpty](#isnotempty)\n- [Coalesce](#coalesce)\n- [CoalesceOrEmpty](#coalesceorempty)\n- [CoalesceSlice](#coalesceslice)\n- [CoalesceSliceOrEmpty](#coalescesliceorempty)\n- [CoalesceMap](#coalescemap)\n- [CoalesceMapOrEmpty](#coalescemaporempty)\n\nFunction helpers:\n\n- [Partial](#partial)\n- [Partial2 -> Partial5](#partial2---partial5)\n\nConcurrency helpers:\n\n- [Attempt](#attempt)\n- [AttemptWhile](#attemptwhile)\n- [AttemptWithDelay](#attemptwithdelay)\n- [AttemptWhileWithDelay](#attemptwhilewithdelay)\n- [Debounce](#debounce)\n- [DebounceBy](#debounceby)\n- [Throttle](#throttle)\n- [ThrottleWithCount](#throttle)\n- [ThrottleBy](#throttle)\n- [ThrottleByWithCount](#throttle)\n- [Synchronize](#synchronize)\n- [Async](#async)\n- [Async{0->6}](#async0-6)\n- [Transaction](#transaction)\n- [WaitFor](#waitfor)\n- [WaitForWithContext](#waitforwithcontext)\n\nError handling:\n\n- [Validate](#validate)\n- [Must](#must)\n- [Try](#try)\n- [Try1 -> Try6](#try0-6)\n- [TryOr](#tryor)\n- [TryOr1 -> TryOr6](#tryor0-6)\n- [TryCatch](#trycatch)\n- [TryWithErrorValue](#trywitherrorvalue)\n- [TryCatchWithErrorValue](#trycatchwitherrorvalue)\n- [ErrorsAs](#errorsas)\n- [Assert](#assert)\n- [Assertf](#assertf)\n\nConstraints:\n\n- Clonable\n\n### Filter\n\nIterates over a collection and returns a slice of all the elements the predicate function returns `true` for.\n\n```go\neven := lo.Filter([]int{1, 2, 3, 4}, func(x int, index int) bool {\n    return x%2 == 0\n})\n\u002F\u002F []int{2, 4}\n```\n\n```go\n\u002F\u002F Use FilterErr when the predicate can return an error\neven, err := lo.FilterErr([]int{1, 2, 3, 4}, func(x int, _ int) (bool, error) {\n    if x == 3 {\n        return false, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n\u002F\u002F []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FApjg3WeSi7K)]\n\nMutable: like `lo.Filter()`, but the slice is updated in place.\n\n```go\nimport lom \"github.com\u002Fsamber\u002Flo\u002Fmutable\"\n\nlist := []int{1, 2, 3, 4}\nnewList := lom.Filter(list, func(x int) bool {\n    return x%2 == 0\n})\n\nlist\n\u002F\u002F []int{2, 4, 3, 4}\n\nnewList\n\u002F\u002F []int{2, 4}\n```\n\n### Map\n\nManipulates a slice of one type and transforms it into a slice of another type:\n\n```go\nimport \"github.com\u002Fsamber\u002Flo\"\n\nlo.Map([]int64{1, 2, 3, 4}, func(x int64, index int) string {\n    return strconv.FormatInt(x, 10)\n})\n\u002F\u002F []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\n```go\n\u002F\u002F Use MapErr when the transform function can return an error\nresult, err := lo.MapErr([]int{1, 2, 3, 4}, func(x int, _ int) (string, error) {\n    if x == 3 {\n        return \"\", fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return strconv.Itoa(x), nil\n})\n\u002F\u002F []string(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FOkPcYAhBo0D)]\n\nParallel processing: like `lo.Map()`, but the transform function is called in a goroutine. Results are returned in the same order.\n\n```go\nimport lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n\nlop.Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string {\n    return strconv.FormatInt(x, 10)\n})\n\u002F\u002F []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FsCJaB3quRMC)]\n\nMutable: like `lo.Map()`, but the slice is updated in place.\n\n```go\nimport lom \"github.com\u002Fsamber\u002Flo\u002Fmutable\"\n\nlist := []int{1, 2, 3, 4}\nlom.Map(list, func(x int) int {\n    return x*2\n})\n\u002F\u002F []int{2, 4, 6, 8}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F0jY3Z0B7O_5)]\n\n### UniqMap\n\nManipulates a slice and transforms it to a slice of another type with unique values.\n\n```go\ntype User struct {\n    Name string\n    Age  int\n}\nusers := []User{{Name: \"Alex\", Age: 10}, {Name: \"Alex\", Age: 12}, {Name: \"Bob\", Age: 11}, {Name: \"Alice\", Age: 20}}\n\nnames := lo.UniqMap(users, func(u User, index int) string {\n    return u.Name\n})\n\u002F\u002F []string{\"Alex\", \"Bob\", \"Alice\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FfygzLBhvUdB)]\n\n### FilterMap\n\nReturns a slice obtained after both filtering and mapping using the given callback function.\n\nThe callback function should return two values: the result of the mapping operation and whether the result element should be included or not.\n\n```go\nmatching := lo.FilterMap([]string{\"cpu\", \"gpu\", \"mouse\", \"keyboard\"}, func(x string, _ int) (string, bool) {\n    if strings.HasSuffix(x, \"pu\") {\n        return \"xpu\", true\n    }\n    return \"\", false\n})\n\u002F\u002F []string{\"xpu\", \"xpu\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F-AuYXfy7opz)]\n\n### FlatMap\n\nManipulates a slice and transforms and flattens it to a slice of another type. The transform function can either return a slice or a `nil`, and in the `nil` case no value is added to the final slice.\n\n```go\nlo.FlatMap([]int64{0, 1, 2}, func(x int64, _ int) []string {\n    return []string{\n        strconv.FormatInt(x, 10),\n        strconv.FormatInt(x, 10),\n    }\n})\n\u002F\u002F []string{\"0\", \"0\", \"1\", \"1\", \"2\", \"2\"}\n```\n\n```go\n\u002F\u002F Use FlatMapErr when the transform function can return an error\nresult, err := lo.FlatMapErr([]int64{0, 1, 2, 3}, func(x int64, _ int) ([]string, error) {\n    if x == 2 {\n        return nil, fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}, nil\n})\n\u002F\u002F []string(nil), error(\"number 2 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FYSoYmQTA8-U)]\n\n### Reduce\n\nReduces a collection to a single value. The value is calculated by accumulating the result of running each element in the collection through an accumulator function. Each successive invocation is supplied with the return value returned by the previous call.\n\n```go\nsum := lo.Reduce([]int{1, 2, 3, 4}, func(agg int, item int, _ int) int {\n    return agg + item\n}, 0)\n\u002F\u002F 10\n```\n\n```go\n\u002F\u002F Use ReduceErr when the accumulator function can return an error\nresult, err := lo.ReduceErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    if item == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return agg + item, nil\n}, 0)\n\u002F\u002F 0, error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FR4UHXZNaaUG)]\n\n### ReduceRight\n\nLike `lo.Reduce` except that it iterates over elements of collection from right to left.\n\n```go\nresult := lo.ReduceRight([][]int{{0, 1}, {2, 3}, {4, 5}}, func(agg []int, item []int, _ int) []int {\n    return append(agg, item...)\n}, []int{})\n\u002F\u002F []int{4, 5, 2, 3, 0, 1}\n```\n\n```go\n\u002F\u002F Use ReduceRightErr when the accumulator function can return an error\nresult, err := lo.ReduceRightErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    if item == 2 {\n        return 0, fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return agg + item, nil\n}, 0)\n\u002F\u002F 0, error(\"number 2 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FFq3W70l7wXF)]\n\n### ForEach\n\nIterates over elements of a collection and invokes the function over each element.\n\n```go\nimport \"github.com\u002Fsamber\u002Flo\"\n\nlo.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    println(x)\n})\n\u002F\u002F prints \"hello\\nworld\\n\"\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FoofyiUPRf8t)]\n\nParallel processing: like `lo.ForEach()`, but the callback is called as a goroutine.\n\n```go\nimport lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n\nlop.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    println(x)\n})\n\u002F\u002F prints \"hello\\nworld\\n\" or \"world\\nhello\\n\"\n```\n\n### ForEachWhile\n\nIterates over collection elements and invokes iteratee for each element collection return value decide to continue or break, like do while().\n\n```go\nlist := []int64{1, 2, -42, 4}\n\nlo.ForEachWhile(list, func(x int64, _ int) bool {\n\tif x \u003C 0 {\n\t\treturn false\n\t}\n\tfmt.Println(x)\n\treturn true\n})\n\u002F\u002F 1\n\u002F\u002F 2\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FQnLGt35tnow)]\n\n### Times\n\nTimes invokes the iteratee n times, returning a slice of the results of each invocation. The iteratee is invoked with index as argument.\n\n```go\nimport \"github.com\u002Fsamber\u002Flo\"\n\nlo.Times(3, func(i int) string {\n    return strconv.FormatInt(int64(i), 10)\n})\n\u002F\u002F []string{\"0\", \"1\", \"2\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FvgQj3Glr6lT)]\n\nParallel processing: like `lo.Times()`, but callback is called in goroutine.\n\n```go\nimport lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n\nlop.Times(3, func(i int) string {\n    return strconv.FormatInt(int64(i), 10)\n})\n\u002F\u002F []string{\"0\", \"1\", \"2\"}\n```\n\n### Uniq\n\nReturns a duplicate-free version of a slice, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the slice.\n\n```go\nuniqValues := lo.Uniq([]int{1, 2, 2, 1})\n\u002F\u002F []int{1, 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FDTzbeXZ6iEN)]\n\n### UniqBy\n\nReturns a duplicate-free version of a slice, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n\n```go\nuniqValues := lo.UniqBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n\u002F\u002F []int{0, 1, 2}\n```\n\n```go\n\u002F\u002F Use UniqByErr when the iteratee function can return an error\nresult, err := lo.UniqByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n\u002F\u002F []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fg42Z3QSb53u)]\n\n### GroupBy\n\nReturns an object composed of keys generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com\u002Fsamber\u002Flo\"\n\ngroups := lo.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n\u002F\u002F map[int][]int{0: []int{0, 3}, 1: []int{1, 4}, 2: []int{2, 5}}\n```\n\n```go\n\u002F\u002F Use GroupByErr when the iteratee function can return an error\nresult, err := lo.GroupByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n\u002F\u002F map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FXnQBd_v6brd)]\n\nParallel processing: like `lo.GroupBy()`, but callback is called in goroutine.\n\n```go\nimport lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n\nlop.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n\u002F\u002F map[int][]int{0: []int{0, 3}, 1: []int{1, 4}, 2: []int{2, 5}}\n```\n\n### GroupByMap\n\nReturns an object composed of keys generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com\u002Fsamber\u002Flo\"\n\ngroups := lo.GroupByMap([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int) {\n    return i%3, i*2\n})\n\u002F\u002F map[int][]int{0: []int{0, 6}, 1: []int{2, 8}, 2: []int{4, 10}}\n```\n\n```go\n\u002F\u002F Use GroupByMapErr when the transform function can return an error\nresult, err := lo.GroupByMapErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int, error) {\n    if i == 3 {\n        return 0, 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, i * 2, nil\n})\n\u002F\u002F map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FiMeruQ3_W80)]\n\n### Chunk\n\nReturns a slice of elements split into groups of length size. If the slice can't be split evenly, the final chunk will be the remaining elements.\n\n```go\nlo.Chunk([]int{0, 1, 2, 3, 4, 5}, 2)\n\u002F\u002F [][]int{{0, 1}, {2, 3}, {4, 5}}\n\nlo.Chunk([]int{0, 1, 2, 3, 4, 5, 6}, 2)\n\u002F\u002F [][]int{{0, 1}, {2, 3}, {4, 5}, {6}}\n\nlo.Chunk([]int{}, 2)\n\u002F\u002F [][]int{}\n\nlo.Chunk([]int{0}, 2)\n\u002F\u002F [][]int{{0}}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FkEMkFbdu85g)]\n\n### Window\n\nCreates a slice of sliding windows of a given size. Each window shares size-1 elements with the previous one. This is equivalent to `Sliding(collection, size, 1)`.\n\n```go\nlo.Window([]int{1, 2, 3, 4, 5}, 3)\n\u002F\u002F [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}\n\nlo.Window([]float64{20, 22, 21, 23, 24}, 3)\n\u002F\u002F [][]float64{{20, 22, 21}, {22, 21, 23}, {21, 23, 24}}\n```\n\n### Sliding\n\nCreates a slice of sliding windows of a given size with a given step. If step is equal to size, windows have no common elements (similar to Chunk). If step is less than size, windows share common elements.\n\n```go\n\u002F\u002F Windows with shared elements (step \u003C size)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 1)\n\u002F\u002F [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}\n\n\u002F\u002F Windows with no shared elements (step == size, like Chunk)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 3)\n\u002F\u002F [][]int{{1, 2, 3}, {4, 5, 6}}\n\n\u002F\u002F Step > size (skipping elements)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6, 7, 8}, 2, 3)\n\u002F\u002F [][]int{{1, 2}, {4, 5}, {7, 8}}\n```\n\n### PartitionBy\n\nReturns a slice of elements split into groups. The order of grouped values is determined by the order they occur in collection. The grouping is generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com\u002Fsamber\u002Flo\"\n\npartitions := lo.PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, func(x int) string {\n    if x \u003C 0 {\n        return \"negative\"\n    } else if x%2 == 0 {\n        return \"even\"\n    }\n    return \"odd\"\n})\n\u002F\u002F [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}\n```\n\n```go\n\u002F\u002F Use PartitionByErr when the iteratee function can return an error\nresult, err := lo.PartitionByErr([]int{-2, -1, 0, 1, 2}, func(x int) (string, error) {\n    if x == 0 {\n        return \"\", fmt.Errorf(\"zero is not allowed\")\n    }\n    if x \u003C 0 {\n        return \"negative\", nil\n    } else if x%2 == 0 {\n        return \"even\", nil\n    }\n    return \"odd\", nil\n})\n\u002F\u002F [][]int(nil), error(\"zero is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FNfQ_nGjkgXW)]\n\nParallel processing: like `lo.PartitionBy()`, but callback is called in goroutine. Results are returned in the same order.\n\n```go\nimport lop \"github.com\u002Fsamber\u002Flo\u002Fparallel\"\n\npartitions := lop.PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, func(x int) string {\n    if x \u003C 0 {\n        return \"negative\"\n    } else if x%2 == 0 {\n        return \"even\"\n    }\n    return \"odd\"\n})\n\u002F\u002F [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}\n```\n\n### Flatten\n\nReturns a slice a single level deep.\n\n```go\nflat := lo.Flatten([][]int{{0, 1}, {2, 3, 4, 5}})\n\u002F\u002F []int{0, 1, 2, 3, 4, 5}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Frbp9ORaMpjw)]\n\n### Concat\n\nReturns a new slice containing all the elements in collections. Concat conserves the order of the elements.\n\n```go\nslice := lo.Concat([]int{1, 2}, []int{3, 4})\n\u002F\u002F []int{1, 2, 3, 4}\n\nslice := lo.Concat(nil, []int{1, 2}, nil, []int{3, 4}, nil)\n\u002F\u002F []int{1, 2, 3, 4}\n\nslice := lo.Concat[int]()\n\u002F\u002F []int{}\n```\n### Interleave\n\nRound-robin alternating input slices and sequentially appending value at index into result.\n\n```go\ninterleaved := lo.Interleave([]int{1, 4, 7}, []int{2, 5, 8}, []int{3, 6, 9})\n\u002F\u002F []int{1, 2, 3, 4, 5, 6, 7, 8, 9}\n\ninterleaved := lo.Interleave([]int{1}, []int{2, 5, 8}, []int{3, 6}, []int{4, 7, 9, 10})\n\u002F\u002F []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F-RJkTLQEDVt)]\n\n### Shuffle\n\nReturns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\n\n⚠️ This helper is **mutable**.\n\n```go\nimport lom \"github.com\u002Fsamber\u002Flo\u002Fmutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Shuffle(list)\n\nlist\n\u002F\u002F []int{1, 4, 0, 3, 5, 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F2xb3WdLjeSJ)]\n\n### Reverse\n\nReverses a slice so that the first element becomes the last, the second element becomes the second to last, and so on.\n\n⚠️ This helper is **mutable**.\n\n```go\nimport lom \"github.com\u002Fsamber\u002Flo\u002Fmutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Reverse(list)\n\nlist\n\u002F\u002F []int{5, 4, 3, 2, 1, 0}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FO-M5pmCRgzV)]\n\n### Fill\n\nFills elements of a slice with `initial` value.\n\n```go\ntype foo struct {\n  bar string\n}\n\nfunc (f foo) Clone() foo {\n  return foo{f.bar}\n}\n\ninitializedSlice := lo.Fill([]foo{foo{\"a\"}, foo{\"a\"}}, foo{\"b\"})\n\u002F\u002F []foo{foo{\"b\"}, foo{\"b\"}}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FVwR34GzqEub)]\n\n### Repeat\n\nBuilds a slice with N copies of initial value.\n\n```go\ntype foo struct {\n  bar string\n}\n\nfunc (f foo) Clone() foo {\n  return foo{f.bar}\n}\n\nslice := lo.Repeat(2, foo{\"a\"})\n\u002F\u002F []foo{foo{\"a\"}, foo{\"a\"}}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fg3uHXbmc3b6)]\n\n### RepeatBy\n\nBuilds a slice with values returned by N calls of callback.\n\n```go\nslice := lo.RepeatBy(0, func (i int) string {\n    return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n})\n\u002F\u002F []string{}\n\nslice := lo.RepeatBy(5, func(i int) string {\n    return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n})\n\u002F\u002F []string{\"0\", \"1\", \"4\", \"9\", \"16\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FozZLCtX_hNU)]\n\nWith error handling:\n\n```go\nslice, err := lo.RepeatByErr(5, func(i int) (string, error) {\n    if i == 3 {\n        return \"\", fmt.Errorf(\"index 3 is not allowed\")\n    }\n    return fmt.Sprintf(\"item-%d\", i), nil\n})\n\u002F\u002F []string(nil), error(\"index 3 is not allowed\")\n```\n\n### KeyBy\n\nTransforms a slice or a slice of structs to a map based on a pivot callback.\n\n```go\nm := lo.KeyBy([]string{\"a\", \"aa\", \"aaa\"}, func(str string) int {\n    return len(str)\n})\n\u002F\u002F map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}\n\ntype Character struct {\n  dir  string\n  code int\n}\ncharacters := []Character{\n    {dir: \"left\", code: 97},\n    {dir: \"right\", code: 100},\n}\nresult := lo.KeyBy(characters, func(char Character) string {\n    return string(rune(char.code))\n})\n\u002F\u002Fmap[a:{dir:left code:97} d:{dir:right code:100}]\n```\n\n```go\nresult, err := lo.KeyByErr([]string{\"a\", \"aa\", \"aaa\", \"\"}, func(str string) (int, error) {\n    if str == \"\" {\n        return 0, fmt.Errorf(\"empty string not allowed\")\n    }\n    return len(str), nil\n})\n\u002F\u002F map[int]string(nil), error(\"empty string not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FmdaClUAT-zZ)]\n\n### SliceToMap (alias: Associate)\n\nReturns a map containing key-value pairs provided by transform function applied to elements of the given slice.\nIf any of two pairs have the same key the last one gets added to the map.\n\nThe order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n\n```go\nin := []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}}\n\naMap := lo.SliceToMap(in, func (f *foo) (string, int) {\n    return f.baz, f.bar\n})\n\u002F\u002F map[string][int]{ \"apple\":1, \"banana\":2 }\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FWHa2CfMO3Lr)]\n\n### FilterSliceToMap\n\nReturns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n\nIf any of two pairs have the same key the last one gets added to the map.\n\nThe order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n\nThe third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n\n```go\nlist := []string{\"a\", \"aa\", \"aaa\"}\n\nresult := lo.FilterSliceToMap(list, func(str string) (string, int, bool) {\n    return str, len(str), len(str) > 1\n})\n\u002F\u002F map[string][int]{\"aa\":2 \"aaa\":3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F2z0rDz2ZSGU)]\n\n### Keyify\n\nReturns a map with each unique element of the slice as a key.\n\n```go\nset := lo.Keyify([]int{1, 1, 2, 3, 4})\n\u002F\u002F map[int]struct{}{1:{}, 2:{}, 3:{}, 4:{}}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FRYhhM_csqIG)]\n\n### Take\n\nTakes the first n elements from a slice.\n\n```go\nl := lo.Take([]int{0, 1, 2, 3, 4, 5}, 3)\n\u002F\u002F []int{0, 1, 2}\n\nl := lo.Take([]int{0, 1, 2}, 5)\n\u002F\u002F []int{0, 1, 2}\n```\n\n### TakeWhile\n\nTakes elements from the beginning while the predicate returns true.\n\n```go\nl := lo.TakeWhile([]int{0, 1, 2, 3, 4, 5}, func(val int) bool {\n    return val \u003C 3\n})\n\u002F\u002F []int{0, 1, 2}\n\nl := lo.TakeWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\"}, func(val string) bool {\n    return len(val) \u003C= 2\n})\n\u002F\u002F []string{\"a\", \"aa\"}\n```\n\n### TakeFilter\n\nFilters elements and takes the first n elements that match the predicate. Equivalent to calling Take(Filter(...)), but more efficient as it stops after finding n matches.\n\n```go\nl := lo.TakeFilter([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, func(val int, index int) bool {\n    return val%2 == 0\n})\n\u002F\u002F []int{2, 4, 6}\n\nl := lo.TakeFilter([]string{\"a\", \"aa\", \"aaa\", \"aaaa\"}, 2, func(val string, index int) bool {\n    return len(val) > 1\n})\n\u002F\u002F []string{\"aa\", \"aaa\"}\n```\n\n### Drop\n\nDrops n elements from the beginning of a slice.\n\n```go\nl := lo.Drop([]int{0, 1, 2, 3, 4, 5}, 2)\n\u002F\u002F []int{2, 3, 4, 5}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FJswS7vXRJP2)]\n\n### DropRight\n\nDrops n elements from the end of a slice.\n\n```go\nl := lo.DropRight([]int{0, 1, 2, 3, 4, 5}, 2)\n\u002F\u002F []int{0, 1, 2, 3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FGG0nXkSJJa3)]\n\n### DropWhile\n\nDrop elements from the beginning of a slice while the predicate returns true.\n\n```go\nl := lo.DropWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) \u003C= 2\n})\n\u002F\u002F []string{\"aaa\", \"aa\", \"aa\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F7gBPYw2IK16)]\n\n### DropRightWhile\n\nDrop elements from the end of a slice while the predicate returns true.\n\n```go\nl := lo.DropRightWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) \u003C= 2\n})\n\u002F\u002F []string{\"a\", \"aa\", \"aaa\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F3-n71oEC0Hz)]\n\n### DropByIndex\n\nDrops elements from a slice by the index. A negative index will drop elements from the end of the slice.\n\n```go\nl := lo.DropByIndex([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)\n\u002F\u002F []int{0, 1, 3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FJswS7vXRJP2)]\n\n### Reject\n\nThe opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n\n```go\nodd := lo.Reject([]int{1, 2, 3, 4}, func(x int, _ int) bool {\n    return x%2 == 0\n})\n\u002F\u002F []int{1, 3}\n```\n\n```go\n\u002F\u002F Use RejectErr when the predicate can return an error\nodd, err := lo.RejectErr([]int{1, 2, 3, 4}, func(x int, _ int) (bool, error) {\n    if x == 3 {\n        return false, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n\u002F\u002F []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FYkLMODy1WEL)]\n\n### RejectMap\n\nThe opposite of FilterMap, this method returns a slice obtained after both filtering and mapping using the given callback function.\n\nThe callback function should return two values:\n\n- the result of the mapping operation and\n- whether the result element should be included or not.\n\n```go\nitems := lo.RejectMap([]int{1, 2, 3, 4}, func(x int, _ int) (int, bool) {\n    return x*10, x%2 == 0\n})\n\u002F\u002F []int{10, 30}\n```\n\n### FilterReject\n\nMixes Filter and Reject, this method returns two slices, one for the elements of collection that predicate returns true for and one for the elements that predicate does not return true for.\n\n```go\nkept, rejected := lo.FilterReject([]int{1, 2, 3, 4}, func(x int, _ int) bool {\n    return x%2 == 0\n})\n\u002F\u002F []int{2, 4}\n\u002F\u002F []int{1, 3}\n```\n\n### Count\n\nCounts the number of elements in the collection that equal value.\n\n```go\ncount := lo.Count([]int{1, 5, 1}, 1)\n\u002F\u002F 2\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FY3FlK54yveC)]\n\n### CountBy\n\nCounts the number of elements in the collection for which predicate is true.\n\n```go\ncount := lo.CountBy([]int{1, 5, 1}, func(i int) bool {\n    return i \u003C 4\n})\n\u002F\u002F 2\n```\n\n```go\n\u002F\u002F Use CountByErr when the predicate can return an error\ncount, err := lo.CountByErr([]int{1, 5, 1}, func(i int) (bool, error) {\n    if i == 5 {\n        return false, fmt.Errorf(\"5 not allowed\")\n    }\n    return i \u003C 4, nil\n})\n\u002F\u002F 0, error(\"5 not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FByQbNYQQi4X)]\n\n### CountValues\n\nCounts the number of each element in the collection.\n\n```go\nlo.CountValues([]int{})\n\u002F\u002F map[int]int{}\n\nlo.CountValues([]int{1, 2})\n\u002F\u002F map[int]int{1: 1, 2: 1}\n\nlo.CountValues([]int{1, 2, 2})\n\u002F\u002F map[int]int{1: 1, 2: 2}\n\nlo.CountValues([]string{\"foo\", \"bar\", \"\"})\n\u002F\u002F map[string]int{\"\": 1, \"foo\": 1, \"bar\": 1}\n\nlo.CountValues([]string{\"foo\", \"bar\", \"bar\"})\n\u002F\u002F map[string]int{\"foo\": 1, \"bar\": 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F-p-PyLT4dfy)]\n\n### CountValuesBy\n\nCounts the number of each element in the collection. It is equivalent to chaining lo.Map and lo.CountValues.\n\n```go\nisEven := func(v int) bool {\n    return v%2==0\n}\n\nlo.CountValuesBy([]int{}, isEven)\n\u002F\u002F map[bool]int{}\n\nlo.CountValuesBy([]int{1, 2}, isEven)\n\u002F\u002F map[bool]int{false: 1, true: 1}\n\nlo.CountValuesBy([]int{1, 2, 2}, isEven)\n\u002F\u002F map[bool]int{false: 1, true: 2}\n\nlength := func(v string) int {\n    return len(v)\n}\n\nlo.CountValuesBy([]string{\"foo\", \"bar\", \"\"}, length)\n\u002F\u002F map[int]int{0: 1, 3: 2}\n\nlo.CountValuesBy([]string{\"foo\", \"bar\", \"bar\"}, length)\n\u002F\u002F map[int]int{3: 3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F2U0dG1SnOmS)]\n\n### Subset\n\nReturns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\n\nsub := lo.Subset(in, 2, 3)\n\u002F\u002F []int{2, 3, 4}\n\nsub := lo.Subset(in, -4, 3)\n\u002F\u002F []int{1, 2, 3}\n\nsub := lo.Subset(in, -2, math.MaxUint)\n\u002F\u002F []int{3, 4}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FtOQu1GhFcog)]\n\n### Slice\n\nReturns a copy of a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\n\nslice := lo.Slice(in, 0, 5)\n\u002F\u002F []int{0, 1, 2, 3, 4}\n\nslice := lo.Slice(in, 2, 3)\n\u002F\u002F []int{2}\n\nslice := lo.Slice(in, 2, 6)\n\u002F\u002F []int{2, 3, 4}\n\nslice := lo.Slice(in, 4, 3)\n\u002F\u002F []int{}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F8XWYhfMMA1h)]\n\n### Replace\n\nReturns a copy of the slice with the first n non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, 1)\n\u002F\u002F []int{42, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, -1, 42, 1)\n\u002F\u002F []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, 2)\n\u002F\u002F []int{42, 1, 42, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, -1)\n\u002F\u002F []int{42, 1, 42, 1, 2, 3, 42}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FXfPzmf9gql6)]\n\n### ReplaceAll\n\nReturns a copy of the slice with all non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.ReplaceAll(in, 0, 42)\n\u002F\u002F []int{42, 1, 42, 1, 2, 3, 42}\n\nslice := lo.ReplaceAll(in, -1, 42)\n\u002F\u002F []int{0, 1, 0, 1, 2, 3, 0}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fa9xZFUHfYcV)]\n\n### Clone\n\nReturns a shallow copy of the collection.\n\n```go\nin := []int{1, 2, 3, 4, 5}\ncloned := lo.Clone(in)\n\u002F\u002F Verify it's a different slice by checking that modifying one doesn't affect the other\nin[0] = 99\n\u002F\u002F cloned is []int{1, 2, 3, 4, 5}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FhgHmoOIxmuH)]\n\n### Compact\n\nReturns a slice of all non-zero elements.\n\n```go\nin := []string{\"\", \"foo\", \"\", \"bar\", \"\"}\n\nslice := lo.Compact(in)\n\u002F\u002F []string{\"foo\", \"bar\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FtXiy-iK6PAc)]\n\n### IsSorted\n\nChecks if a slice is sorted.\n\n```go\nslice := lo.IsSorted([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})\n\u002F\u002F true\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fmc3qR-t4mcx)]\n\n### IsSortedBy\n\nChecks if a slice is sorted by iteratee.\n\n```go\nslice := lo.IsSortedBy([]string{\"a\", \"bb\", \"ccc\"}, func(s string) int {\n    return len(s)\n})\n\u002F\u002F true\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FwiG6XyBBu49)]\n\n### Splice\n\nSplice inserts multiple elements at index i. A negative index counts back from the end of the slice. The helper is protected against overflow errors.\n\n```go\nresult := lo.Splice([]string{\"a\", \"b\"}, 1, \"1\", \"2\")\n\u002F\u002F []string{\"a\", \"1\", \"2\", \"b\"}\n\n\u002F\u002F negative\nresult = lo.Splice([]string{\"a\", \"b\"}, -1, \"1\", \"2\")\n\u002F\u002F []string{\"a\", \"1\", \"2\", \"b\"}\n\n\u002F\u002F overflow\nresult = lo.Splice([]string{\"a\", \"b\"}, 42, \"1\", \"2\")\n\u002F\u002F []string{\"a\", \"b\", \"1\", \"2\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FG5_GhkeSUBA)]\n\n### Cut\n\nSlices collection around the first instance of separator, returning the part of collection before and after separator. The found result reports whether separator appears in collection. If separator does not appear in s, cut returns collection, empty slice of []T, false.\n\n```go\nactualLeft, actualRight, result = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"c\", \"d\"})\n\u002F\u002F actualLeft: []string{\"a\"}\n\u002F\u002F actualRight: []string{\"e\", \"f\", \"g\"}\n\u002F\u002F result: true\n\nresult = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"z\"})\n\u002F\u002F actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F actualRight: []string{}\n\u002F\u002F result: false\n\nresult = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\u002F\u002F actualLeft: []string{}\n\u002F\u002F actualRight: []string{\"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: true\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FGiL3qhpIP3f)]\n\n### CutPrefix\n\nReturns collection without the provided leading prefix []T and reports whether it found the prefix. If s doesn't start with prefix, CutPrefix returns collection, false. If prefix is the empty []T, CutPrefix returns collection, true.\n\n```go\nactualRight, result = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\"})\n\u002F\u002F actualRight: []string{\"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: true\n\nresult = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\"})\n\u002F\u002F actualRight: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: false\n\nresult = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\u002F\u002F actualRight: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: true\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F7Plak4a1ICl)]\n\n### CutSuffix\n\nReturns collection without the provided ending suffix []T and reports whether it found the suffix. If it doesn't end with suffix, CutSuffix returns collection, false. If suffix is the empty []T, CutSuffix returns collection, true.\n\n```go\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"f\", \"g\"})\n\u002F\u002F actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\"}\n\u002F\u002F result: true\n\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\"})\n\u002F\u002F actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: false\n\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\u002F\u002F actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\u002F\u002F result: true\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F7FKfBFvPTaT)]\n\n### Trim\n\nRemoves all the leading and trailing cutset from the collection.\n\n```go\nresult := lo.Trim([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n\u002F\u002F []int{2, 0, 3}\n\nresult := lo.Trim([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n\u002F\u002F []string{\"hello\", \"world\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F1an9mxLdRG5)]\n\n### TrimLeft\n\nRemoves all the leading cutset from the collection.\n\n```go\nresult := lo.TrimLeft([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n\u002F\u002F []int{2, 0, 3, 0}\n\nresult := lo.TrimLeft([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n\u002F\u002F []string{\"hello\", \"world\", \" \"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F74aqfAYLmyi)]\n\n### TrimPrefix\n\nRemoves all the leading prefix from the collection.\n\n```go\nresult := lo.TrimPrefix([]int{1, 2, 1, 2, 3, 1, 2, 4}, []int{1, 2})\n\u002F\u002F []int{3, 1, 2, 4}\n\nresult := lo.TrimPrefix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"hello\"})\n\u002F\u002F []string{\"world\", \"hello\", \"test\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FSHO6X-YegPg)]\n\n### TrimRight\n\nRemoves all the trailing cutset from the collection.\n\n```go\nresult := lo.TrimRight([]int{0, 1, 2, 0, 3, 0}, []int{0, 3})\n\u002F\u002F []int{0, 1, 2}\n\nresult := lo.TrimRight([]string{\"hello\", \"world\", \"  \"}, []string{\" \", \"\"})\n\u002F\u002F []string{\"hello\", \"world\", \"\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FMRpAfR6sf0g)]\n\n### TrimSuffix\n\nRemoves all the trailing suffix from the collection.\n\n```go\nresult := lo.TrimSuffix([]int{1, 2, 3, 1, 2, 4, 2, 4, 2, 4}, []int{2, 4})\n\u002F\u002F []int{1, 2, 3, 1}\n\nresult := lo.TrimSuffix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"test\"})\n\u002F\u002F []string{\"hello\", \"world\", \"hello\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FIjEUrV0iofq)]\n\n### Keys\n\nCreates a slice of the map keys.\n\nUse the UniqKeys variant to deduplicate common keys.\n\n```go\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2})\n\u002F\u002F []string{\"foo\", \"bar\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\u002F\u002F []string{\"foo\", \"bar\", \"baz\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n\u002F\u002F []string{\"foo\", \"bar\", \"bar\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FUu11fHASqrU)]\n\n### UniqKeys\n\nCreates a slice of unique map keys.\n\n```go\nkeys := lo.UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\u002F\u002F []string{\"foo\", \"bar\", \"baz\"}\n\nkeys := lo.UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n\u002F\u002F []string{\"foo\", \"bar\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FTPKAb6ILdHk)]\n\n### HasKey\n\nReturns whether the given key exists.\n\n```go\nexists := lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\")\n\u002F\u002F true\n\nexists := lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\")\n\u002F\u002F false\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FaVwubIvECqS)]\n\n### Values\n\nCreates a slice of the map values.\n\nUse the UniqValues variant to deduplicate common values.\n\n```go\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2})\n\u002F\u002F []int{1, 2}\n\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\u002F\u002F []int{1, 2, 3}\n\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 2})\n\u002F\u002F []int{1, 2, 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FnnRTQkzQfF6)]\n\n### UniqValues\n\nCreates a slice of unique map values.\n\n```go\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2})\n\u002F\u002F []int{1, 2}\n\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\u002F\u002F []int{1, 2, 3}\n\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 2})\n\u002F\u002F []int{1, 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fnf6bXMh7rM3)]\n\n### ValueOr\n\nReturns the value of the given key or the fallback value if the key is not present.\n\n```go\nvalue := lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\", 42)\n\u002F\u002F 1\n\nvalue := lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\", 42)\n\u002F\u002F 42\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FbAq9mHErB4V)]\n\n### PickBy\n\nReturns same map type filtered by given predicate.\n\n```go\nm := lo.PickBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n    return value%2 == 1\n})\n\u002F\u002F map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n```go\n\u002F\u002F Use PickByErr when the predicate can return an error\nm, err := lo.PickByErr(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) (bool, error) {\n    if key == \"bar\" {\n        return false, fmt.Errorf(\"bar not allowed\")\n    }\n    return value%2 == 1, nil\n})\n\u002F\u002F map[string]int(nil), error(\"bar not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fkdg8GR_QMmf)]\n\n### PickByKeys\n\nReturns same map type filtered by given keys.\n\n```go\nm := lo.PickByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\"})\n\u002F\u002F map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FR1imbuci9qU)]\n\n### PickByValues\n\nReturns same map type filtered by given values.\n\n```go\nm := lo.PickByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n\u002F\u002F map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F1zdzSvbfsJc)]\n\n### OmitBy\n\nReturns same map type filtered by given predicate.\n\n```go\nm := lo.OmitBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n    return value%2 == 1\n})\n\u002F\u002F map[string]int{\"bar\": 2}\n```\n\n```go\n\u002F\u002F Use OmitByErr when the predicate can return an error\nm, err := lo.OmitByErr(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) (bool, error) {\n    if key == \"bar\" {\n        return false, fmt.Errorf(\"bar not allowed\")\n    }\n    return value%2 == 1, nil\n})\n\u002F\u002F map[string]int(nil), error(\"bar not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FEtBsR43bdsd)]\n\n### OmitByKeys\n\nReturns same map type filtered by given keys.\n\n```go\nm := lo.OmitByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\"})\n\u002F\u002F map[string]int{\"bar\": 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Ft1QjCrs-ysk)]\n\n### OmitByValues\n\nReturns same map type filtered by given values.\n\n```go\nm := lo.OmitByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n\u002F\u002F map[string]int{\"bar\": 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F9UYZi-hrs8j)]\n\n### Entries (alias: ToPairs)\n\nTransforms a map into a slice of key\u002Fvalue pairs.\n\n```go\nentries := lo.Entries(map[string]int{\"foo\": 1, \"bar\": 2})\n\u002F\u002F []lo.Entry[string, int]{\n\u002F\u002F     {\n\u002F\u002F         Key: \"foo\",\n\u002F\u002F         Value: 1,\n\u002F\u002F     },\n\u002F\u002F     {\n\u002F\u002F         Key: \"bar\",\n\u002F\u002F         Value: 2,\n\u002F\u002F     },\n\u002F\u002F }\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F_t4Xe34-Nl5)]\n\n### FromEntries (alias: FromPairs)\n\nTransforms a slice of key\u002Fvalue pairs into a map.\n\n```go\nm := lo.FromEntries([]lo.Entry[string, int]{\n    {\n        Key: \"foo\",\n        Value: 1,\n    },\n    {\n        Key: \"bar\",\n        Value: 2,\n    },\n})\n\u002F\u002F map[string]int{\"foo\": 1, \"bar\": 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FoIr5KHFGCEN)]\n\n### Invert\n\nCreates a map composed of the inverted keys and values. If map contains duplicate values, subsequent values overwrite property assignments of previous values.\n\n```go\nm1 := lo.Invert(map[string]int{\"a\": 1, \"b\": 2})\n\u002F\u002F map[int]string{1: \"a\", 2: \"b\"}\n\nm2 := lo.Invert(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1})\n\u002F\u002F map[int]string{1: \"c\", 2: \"b\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FrFQ4rak6iA1)]\n\n### Assign\n\nMerges multiple maps from left to right.\n\n```go\nmergedMaps := lo.Assign(\n    map[string]int{\"a\": 1, \"b\": 2},\n    map[string]int{\"b\": 3, \"c\": 4},\n)\n\u002F\u002F map[string]int{\"a\": 1, \"b\": 3, \"c\": 4}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FVhwfJOyxf5o)]\n\n### ChunkEntries\n\nSplits a map into a slice of elements in groups of length equal to its size. If the map cannot be split evenly, the final chunk will contain the remaining elements.\n\n```go\nmaps := lo.ChunkEntries(\n    map[string]int{\n        \"a\": 1,\n        \"b\": 2,\n        \"c\": 3,\n        \"d\": 4,\n        \"e\": 5,\n    },\n    3,\n)\n\u002F\u002F []map[string]int{\n\u002F\u002F    {\"a\": 1, \"b\": 2, \"c\": 3},\n\u002F\u002F    {\"d\": 4, \"e\": 5},\n\u002F\u002F }\n```\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FX_YQL6mmoD-)]\n\n### MapKeys\n\nManipulates map keys and transforms it to a map of another type.\n\n```go\nm2 := lo.MapKeys(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(_ int, v int) string {\n    return strconv.FormatInt(int64(v), 10)\n})\n\u002F\u002F map[string]int{\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}\n```\n\n```go\n\u002F\u002F Use MapKeysErr when the iteratee can return an error\nm2, err := lo.MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3}, func(_ int, v int) (string, error) {\n    if v == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.FormatInt(int64(v), 10), nil\n})\n\u002F\u002F map[string]int(nil), error(\"even number not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F9_4WPIqOetJ)]\n\n### MapValues\n\nManipulates map values and transforms it to a map of another type.\n\n```go\nm1 := map[int]int64{1: 1, 2: 2, 3: 3}\n\nm2 := lo.MapValues(m1, func(x int64, _ int) string {\n    return strconv.FormatInt(x, 10)\n})\n\u002F\u002F map[int]string{1: \"1\", 2: \"2\", 3: \"3\"}\n```\n\n```go\n\u002F\u002F Use MapValuesErr when the iteratee can return an error\nm1 := map[int]int64{1: 1, 2: 2, 3: 3}\nm2, err := lo.MapValuesErr(m1, func(x int64, _ int) (string, error) {\n    if x == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.FormatInt(x, 10), nil\n})\n\u002F\u002F map[int]string(nil), error(\"even number not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FT_8xAfvcf0W)]\n\n### MapEntries\n\nManipulates map entries and transforms it to a map of another type.\n\n```go\nin := map[string]int{\"foo\": 1, \"bar\": 2}\n\nout := lo.MapEntries(in, func(k string, v int) (int, string) {\n    return v,k\n})\n\u002F\u002F map[int]string{1: \"foo\", 2: \"bar\"}\n```\n\n```go\n\u002F\u002F Use MapEntriesErr when the iteratee can return an error\nin := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\nout, err := lo.MapEntriesErr(in, func(k string, v int) (int, string, error) {\n    if k == \"bar\" {\n        return 0, \"\", fmt.Errorf(\"bar not allowed\")\n    }\n    return v, k, nil\n})\n\u002F\u002F map[int]string(nil), error(\"bar not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FVuvNQzxKimT)]\n\n### MapToSlice\n\nTransforms a map into a slice based on specified iteratee.\n\n```go\nm := map[int]int64{1: 4, 2: 5, 3: 6}\n\ns := lo.MapToSlice(m, func(k int, v int64) string {\n    return fmt.Sprintf(\"%d_%d\", k, v)\n})\n\u002F\u002F []string{\"1_4\", \"2_5\", \"3_6\"}\n```\n\n```go\n\u002F\u002F Use MapToSliceErr when the iteratee can return an error\nm := map[int]int64{1: 4, 2: 5, 3: 6}\ns, err := lo.MapToSliceErr(m, func(k int, v int64) (string, error) {\n    if k == 2 {\n        return \"\", fmt.Errorf(\"key 2 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), nil\n})\n\u002F\u002F []string(nil), error(\"key 2 not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FZuiCZpDt6LD)]\n\n### FilterMapToSlice\n\nTransforms a map into a slice based on specified iteratee. The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice.\n\nIf the boolean is false, the value is not added to the result slice. The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed.\n\n```go\nkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\nresult := lo.FilterMapToSlice(kv, func(k int, v int64) (string, bool) {\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n})\n\u002F\u002F []{\"2_2\", \"4_4\"}\n```\n\n```go\nkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\nresult, err := lo.FilterMapToSliceErr(kv, func(k int, v int64) (string, bool, error) {\n    if k == 3 {\n        return \"\", false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n})\n\u002F\u002F []string(nil), error(\"key 3 not allowed\")\n```\n\n### FilterKeys\n\nTransforms a map into a slice based on predicate returns true for specific elements. It is a mix of `lo.Filter()` and `lo.Keys()`.\n\n```go\nkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\nresult := FilterKeys(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n\u002F\u002F [1]\n```\n\n```go\n\u002F\u002F Use FilterKeysErr when the predicate can return an error\nresult, err := lo.FilterKeysErr(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n\u002F\u002F []int(nil), error(\"key 3 not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FOFlKXlPrBAe)]\n\n### FilterValues\n\nTransforms a map into a slice based on predicate returns true for specific elements. It is a mix of `lo.Filter()` and `lo.Values()`.\n\n```go\nkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\nresult := FilterValues(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n\u002F\u002F [\"foo\"]\n```\n\n```go\n\u002F\u002F Use FilterValuesErr when the predicate can return an error\nresult, err := lo.FilterValuesErr(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n\u002F\u002F []string(nil), error(\"key 3 not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FYVD5r_h-LX-)]\n\n### Range \u002F RangeFrom \u002F RangeWithSteps\n\nCreates a slice of numbers (positive and\u002For negative) progressing from start up to, but not including end.\n\n```go\nresult := lo.Range(4)\n\u002F\u002F [0, 1, 2, 3]\n\nresult := lo.Range(-4)\n\u002F\u002F [0, -1, -2, -3]\n\nresult := lo.RangeFrom(1, 5)\n\u002F\u002F [1, 2, 3, 4, 5]\n\nresult := lo.RangeFrom[float64](1.0, 5)\n\u002F\u002F [1.0, 2.0, 3.0, 4.0, 5.0]\n\nresult := lo.RangeWithSteps(0, 20, 5)\n\u002F\u002F [0, 5, 10, 15]\n\nresult := lo.RangeWithSteps[float32](-1.0, -4.0, -1.0)\n\u002F\u002F [-1.0, -2.0, -3.0]\n\nresult := lo.RangeWithSteps(1, 4, -1)\n\u002F\u002F []\n\nresult := lo.Range(0)\n\u002F\u002F []\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F0r6VimXAi9H)]\n\n### Clamp\n\nClamps number within the inclusive lower and upper bounds.\n\n```go\nr1 := lo.Clamp(0, -10, 10)\n\u002F\u002F 0\n\nr2 := lo.Clamp(-42, -10, 10)\n\u002F\u002F -10\n\nr3 := lo.Clamp(42, -10, 10)\n\u002F\u002F 10\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FRU4lJNC2hlI)]\n\n### Sum\n\nSums the values in a collection.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\nsum := lo.Sum(list)\n\u002F\u002F 15\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FupfeJVqs4Bt)]\n\n### SumBy\n\nSummarizes the values in a collection using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nsum := lo.SumBy(strings, func(item string) int {\n    return len(item)\n})\n\u002F\u002F 6\n```\n\nWith error handling:\n\n```go\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"invalid item: %s\", item)\n    }\n    return len(item), nil\n})\n\u002F\u002F sum: 3, err: invalid item: bar\n```\n\n### Product\n\nCalculates the product of the values in a collection.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\nproduct := lo.Product(list)\n\u002F\u002F 120\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F2_kjM_smtAH)]\n\n### ProductBy\n\nCalculates the product of the values in a collection using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nproduct := lo.ProductBy(strings, func(item string) int {\n    return len(item)\n})\n\u002F\u002F 9\n```\n\n```go\n\u002F\u002F Use ProductByErr when the transform function can return an error\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nproduct, err := lo.ProductByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"bar is not allowed\")\n    }\n    return len(item), nil\n})\n\u002F\u002F 3, error(\"bar is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FwadzrWr9Aer)]\n\n### Mean\n\nCalculates the mean of a collection of numbers.\n\nIf collection is empty 0 is returned.\n\n```go\nmean := lo.Mean([]int{2, 3, 4, 5})\n\u002F\u002F 3\n\nmean := lo.Mean([]float64{2, 3, 4, 5})\n\u002F\u002F 3.5\n\nmean := lo.Mean([]float64{})\n\u002F\u002F 0\n```\n\n### MeanBy\n\nCalculates the mean of a collection of numbers using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nmapper := func(item string) float64 {\n    return float64(len(item))\n}\n\nmean := lo.MeanBy(list, mapper)\n\u002F\u002F 3.5\n\nmean := lo.MeanBy([]float64{}, mapper)\n\u002F\u002F 0\n```\n\n```go\n\u002F\u002F Use MeanByErr when the transform function can return an error\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nmean, err := lo.MeanByErr(list, func(item string) (float64, error) {\n    if item == \"cccc\" {\n        return 0, fmt.Errorf(\"cccc is not allowed\")\n    }\n    return float64(len(item)), nil\n})\n\u002F\u002F 0, error(\"cccc is not allowed\")\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fj7TsVwBOZ7P)]\n\n### Mode\n\nCalculates the mode (most frequent value) of a collection of numbers.\n\nIf multiple values have the same highest frequency, then multiple values are returned.\n\nIf the collection is empty, the zero value of `T[]` is returned.\n\n```go\nmode := lo.Mode([]int{2, 2, 3, 4})\n\u002F\u002F [2]\n\nmode := lo.Mode([]float64{2, 2, 3, 3})\n\u002F\u002F [2, 3]\n\nmode := lo.Mode([]float64{})\n\u002F\u002F []\n\nmode := lo.Mode([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})\n\u002F\u002F [1, 2, 3, 4, 5, 6, 7, 8, 9]\n```\n\n### RandomString\n\nReturns a random string of the specified length and made of the specified charset.\n\n```go\nstr := lo.RandomString(5, lo.LettersCharset)\n\u002F\u002F example: \"eIGbt\"\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FrRseOQVVum4)]\n\n### Substring\n\nReturn part of a string.\n\n```go\nsub := lo.Substring(\"hello\", 2, 3)\n\u002F\u002F \"llo\"\n\nsub := lo.Substring(\"hello\", -4, 3)\n\u002F\u002F \"ell\"\n\nsub := lo.Substring(\"hello\", -2, math.MaxUint)\n\u002F\u002F \"lo\"\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FTQlxQi82Lu1)]\n\n### ChunkString\n\nReturns a slice of strings split into groups of length size. If the string can't be split evenly, the final chunk will be the remaining characters.\n\n```go\nlo.ChunkString(\"123456\", 2)\n\u002F\u002F []string{\"12\", \"34\", \"56\"}\n\nlo.ChunkString(\"1234567\", 2)\n\u002F\u002F []string{\"12\", \"34\", \"56\", \"7\"}\n\nlo.ChunkString(\"\", 2)\n\u002F\u002F []string{\"\"}\n\nlo.ChunkString(\"1\", 2)\n\u002F\u002F []string{\"1\"}\n```\n\nNote: `lo.ChunkString` and `lo.Chunk` functions behave inconsistently for empty input: `lo.ChunkString(\"\", n)` returns `[\"\"]` instead of `[]`. See [#788](https:\u002F\u002Fgithub.com\u002Fsamber\u002Flo\u002Fissues\u002F788).\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F__FLTuJVz54)]\n\n### RuneLength\n\nAn alias to utf8.RuneCountInString which returns the number of runes in string.\n\n```go\nsub := lo.RuneLength(\"hellô\")\n\u002F\u002F 5\n\nsub := len(\"hellô\")\n\u002F\u002F 6\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FtuhgW_lWY8l)]\n\n### PascalCase\n\nConverts string to pascal case.\n\n```go\nstr := lo.PascalCase(\"hello_world\")\n\u002F\u002F HelloWorld\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FDy_V_6DUYhe)]\n\n### CamelCase\n\nConverts string to camel case.\n\n```go\nstr := lo.CamelCase(\"hello_world\")\n\u002F\u002F helloWorld\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FGo6aKwUiq59)]\n\n### KebabCase\n\nConverts string to kebab case.\n\n```go\nstr := lo.KebabCase(\"helloWorld\")\n\u002F\u002F hello-world\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F96gT_WZnTVP)]\n\n### SnakeCase\n\nConverts string to snake case.\n\n```go\nstr := lo.SnakeCase(\"HelloWorld\")\n\u002F\u002F hello_world\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FziB0V89IeVH)]\n\n### Words\n\nSplits string into a slice of its words.\n\n```go\nstr := lo.Words(\"helloWorld\")\n\u002F\u002F []string{\"hello\", \"world\"}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002F-f3VIQqiaVw)]\n\n### Capitalize\n\nConverts the first character of string to upper case and the remaining to lower case.\n\n```go\nstr := lo.Capitalize(\"heLLO\")\n\u002F\u002F Hello\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FuLTZZQXqnsa)]\n\n### Ellipsis\n\nTrims and truncates a string to a specified length in runes (Unicode code points) and appends an ellipsis if truncated. Multi-byte characters such as emoji or CJK ideographs are never split in the middle.\n\n```go\nstr := lo.Ellipsis(\"  Lorem Ipsum  \", 5)\n\u002F\u002F Lo...\n\nstr := lo.Ellipsis(\"Lorem Ipsum\", 100)\n\u002F\u002F Lorem Ipsum\n\nstr := lo.Ellipsis(\"Lorem Ipsum\", 3)\n\u002F\u002F ...\n\nstr := lo.Ellipsis(\"hello 世界! 你好\", 8)\n\u002F\u002F hello...\n\nstr := lo.Ellipsis(\"🏠🐶🐱🌟\", 4)\n\u002F\u002F 🏠🐶🐱🌟\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FqE93rgqe1TW)]\n\n### T2 -> T9\n\nCreates a tuple from a list of values.\n\n```go\ntuple1 := lo.T2(\"x\", 1)\n\u002F\u002F Tuple2[string, int]{A: \"x\", B: 1}\n\nfunc example() (string, int) { return \"y\", 2 }\ntuple2 := lo.T2(example())\n\u002F\u002F Tuple2[string, int]{A: \"y\", B: 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FIllL3ZO4BQm)]\n\n### Unpack2 -> Unpack9\n\nReturns values contained in a tuple.\n\n```go\nr1, r2 := lo.Unpack2(lo.Tuple2[string, int]{\"a\", 1})\n\u002F\u002F \"a\", 1\n```\n\nUnpack is also available as a method of TupleX.\n\n```go\ntuple2 := lo.T2(\"a\", 1)\na, b := tuple2.Unpack()\n\u002F\u002F \"a\", 1\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FxVP_k0kJ96W)]\n\n### Zip2 -> Zip9\n\nZip creates a slice of grouped elements, the first of which contains the first elements of the given slices, the second of which contains the second elements of the given slices, and so on.\n\nWhen collections are different sizes, the Tuple attributes are filled with zero value.\n\n```go\ntuples := lo.Zip2([]string{\"a\", \"b\"}, []int{1, 2})\n\u002F\u002F []Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FjujaA6GaJTp)]\n\n### ZipBy2 -> ZipBy9\n\nZipBy creates a slice of transformed elements, the first of which contains the first elements of the given slices, the second of which contains the second elements of the given slices, and so on.\n\nWhen collections are different sizes, the Tuple attributes are filled with zero value.\n\n```go\nitems := lo.ZipBy2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) string {\n    return fmt.Sprintf(\"%s-%d\", a, b)\n})\n\u002F\u002F []string{\"a-1\", \"b-2\"}\n```\n\nWith error handling:\n\n```go\nitems, err := lo.ZipByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if b == 2 {\n        return \"\", fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n\u002F\u002F []string(nil), error(\"number 2 is not allowed\")\n```\n\n### Unzip2 -> Unzip9\n\nUnzip accepts a slice of grouped elements and creates a slice regrouping the elements to their pre-zip configuration.\n\n```go\na, b := lo.Unzip2([]Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}})\n\u002F\u002F []string{\"a\", \"b\"}\n\u002F\u002F []int{1, 2}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FciHugugvaAW)]\n\n### UnzipBy2 -> UnzipBy9\n\nUnzipBy2 iterates over a collection and creates a slice regrouping the elements to their pre-zip configuration.\n\n```go\na, b := lo.UnzipBy2([]string{\"hello\", \"john\", \"doe\"}, func(str string) (string, int) {\n    return str, len(str)\n})\n\u002F\u002F []string{\"hello\", \"john\", \"doe\"}\n\u002F\u002F []int{5, 4, 3}\n```\n\n```go\na, b, err := lo.UnzipByErr2([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, error) {\n    if str == \"error\" {\n        return \"\", 0, fmt.Errorf(\"error string not allowed\")\n    }\n    return str, len(str), nil\n})\n\u002F\u002F []string{}\n\u002F\u002F []int{}\n\u002F\u002F error string not allowed\n```\n\n### CrossJoin2 -> CrossJoin9\n\nCombines every item from one list with every item from others. It is the cartesian product of lists received as arguments. Returns an empty list if a list is empty.\n\n```go\nresult := lo.CrossJoin2([]string{\"hello\", \"john\", \"doe\"}, []int{1, 2})\n\u002F\u002F lo.Tuple2{\"hello\", 1}\n\u002F\u002F lo.Tuple2{\"hello\", 2}\n\u002F\u002F lo.Tuple2{\"john\", 1}\n\u002F\u002F lo.Tuple2{\"john\", 2}\n\u002F\u002F lo.Tuple2{\"doe\", 1}\n\u002F\u002F lo.Tuple2{\"doe\", 2}\n```\n\n### CrossJoinBy2 -> CrossJoinBy9\n\nCombines every item from one list with every item from others. It is the cartesian product of lists received as arguments. The transform function is used to create the output values. Returns an empty list if a list is empty.\n\n```go\nresult := lo.CrossJoinBy2([]string{\"hello\", \"john\", \"doe\"}, []int{1, 2}, func(a A, b B) string {\n    return fmt.Sprintf(\"%s - %d\", a, b)\n})\n\u002F\u002F \"hello - 1\"\n\u002F\u002F \"hello - 2\"\n\u002F\u002F \"john - 1\"\n\u002F\u002F \"john - 2\"\n\u002F\u002F \"doe - 1\"\n\u002F\u002F \"doe - 2\"\n```\n\nWith error handling:\n\n```go\nresult, err := lo.CrossJoinByErr2([]string{\"hello\", \"john\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if a == \"john\" {\n        return \"\", fmt.Errorf(\"john not allowed\")\n    }\n    return fmt.Sprintf(\"%s - %d\", a, b), nil\n})\n\u002F\u002F []string(nil), error(\"john not allowed\")\n```\n\n### Duration\n\nReturns the time taken to execute a function.\n\n```go\nduration := lo.Duration(func() {\n    \u002F\u002F very long job\n})\n\u002F\u002F 3s\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FHQfbBbAXaFP)]\n\n### Duration0 -> Duration10\n\nReturns the time taken to execute a function.\n\n```go\nduration := lo.Duration0(func() {\n    \u002F\u002F very long job\n})\n\u002F\u002F 3s\n\nerr, duration := lo.Duration1(func() error {\n    \u002F\u002F very long job\n    return errors.New(\"an error\")\n})\n\u002F\u002F an error\n\u002F\u002F 3s\n\nstr, nbr, err, duration := lo.Duration3(func() (string, int, error) {\n    \u002F\u002F very long job\n    return \"hello\", 42, nil\n})\n\u002F\u002F hello\n\u002F\u002F 42\n\u002F\u002F nil\n\u002F\u002F 3s\n```\n\n### ChannelDispatcher\n\nDistributes messages from input channels into N child channels. Close events are propagated to children.\n\nUnderlying channels can have a fixed buffer capacity or be unbuffered when cap is 0.\n\n```go\nch := make(chan int, 42)\nfor i := 0; i \u003C= 10; i++ {\n    ch \u003C- i\n}\n\nchildren := lo.ChannelDispatcher(ch, 5, 10, DispatchingStrategyRoundRobin[int])\n\u002F\u002F []\u003C-chan int{...}\n\nconsumer := func(c \u003C-chan int) {\n    for {\n        msg, ok := \u003C-c\n        if !ok {\n            println(\"closed\")\n\n            break\n        }\n\n        println(msg)\n    }\n}\n\nfor i := range children {\n    go consumer(children[i])\n}\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FUZGu2wVg3J2)]\n\nMany distributions strategies are available:\n\n- [lo.DispatchingStrategyRoundRobin](.\u002Fchannel.go): Distributes messages in a rotating sequential manner.\n- [lo.DispatchingStrategyRandom](.\u002Fchannel.go): Distributes messages in a random manner.\n- [lo.DispatchingStrategyWeightedRandom](.\u002Fchannel.go): Distributes messages in a weighted manner.\n- [lo.DispatchingStrategyFirst](.\u002Fchannel.go): Distributes messages in the first non-full channel.\n- [lo.DispatchingStrategyLeast](.\u002Fchannel.go): Distributes messages in the emptiest channel.\n- [lo.DispatchingStrategyMost](.\u002Fchannel.go): Distributes to the fullest channel.\n\nSome strategies bring fallback, in order to favor non-blocking behaviors. See implementations.\n\nFor custom strategies, just implement the `lo.DispatchingStrategy` prototype:\n\n```go\ntype DispatchingStrategy[T any] func(message T, messageIndex uint64, channels []\u003C-chan T) int\n```\n\nEg:\n\n```go\ntype Message struct {\n    TenantID uuid.UUID\n}\n\nfunc hash(id uuid.UUID) int {\n    h := fnv.New32a()\n    h.Write([]byte(id.String()))\n    return int(h.Sum32())\n}\n\n\u002F\u002F Routes messages per TenantID.\ncustomStrategy := func(message string, messageIndex uint64, channels []\u003C-chan string) int {\n    destination := hash(message) % len(channels)\n\n    \u002F\u002F check if channel is full\n    if len(channels[destination]) \u003C cap(channels[destination]) {\n        return destination\n    }\n\n    \u002F\u002F fallback when child channel is full\n    return utils.DispatchingStrategyRoundRobin(message, uint64(destination), channels)\n}\n\nchildren := lo.ChannelDispatcher(ch, 5, 10, customStrategy)\n...\n```\n\n### SliceToChannel\n\nReturns a read-only channel of collection elements. Channel is closed after last element. Channel capacity can be customized.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\n\nfor v := range lo.SliceToChannel(2, list) {\n    println(v)\n}\n\u002F\u002F prints 1, then 2, then 3, then 4, then 5\n```\n\n[[play](https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FlIbSY3QmiEg)]\n\n### ChannelToSlice\n\nReturns a slice built from channel items. B","samber\u002Flo 是一个基于 Go 1.18+ 泛型的 Lodash 风格的 Go 语言库，提供了丰富的工具函数来简化对切片、映射、字符串、通道和函数的操作。其核心功能包括 map、filter、contains 和 find 等常用方法，旨在提高代码的可读性和开发效率。该库充分利用了 Go 1.18 引入的泛型特性，确保类型安全的同时，提供了简洁易用的 API。samber\u002Flo 适用于需要处理复杂数据结构的场景，特别是在需要频繁使用集合操作的项目中能够显著提升编码体验。",2,"2026-06-11 03:00:30","top_language"]