array.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. package array
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. "regexp"
  7. )
  8. var simpleTypes = []string{
  9. "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8",
  10. "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "string",
  11. }
  12. // Column array column to be new array
  13. // php array_column
  14. func Column(dest, input interface{}, columnKey, indexKey string) {
  15. // data validate
  16. if columnKey == "" && indexKey == "" {
  17. panic("columnKey or indexKey must be at least one has value")
  18. }
  19. // dest interface
  20. dValue := reflect.ValueOf(dest)
  21. if dValue.Kind() != reflect.Ptr || dValue.IsNil() {
  22. panic(fmt.Sprintf("haystack: d type[%T] error", reflect.TypeOf(dValue)))
  23. }
  24. dType, dElemType, dKeyType := indirectForArr(dValue)
  25. if !In(dKeyType, simpleTypes) {
  26. // only support 'simpleType'
  27. panic("haystack: dest key type must be 'simpleType'")
  28. }
  29. if indexKey != "" {
  30. if dType != reflect.Map {
  31. panic("haystack: dest type must be map")
  32. }
  33. } else {
  34. if dType != reflect.Slice && dType != reflect.Array {
  35. panic("haystack: dest type must be slice or array ")
  36. }
  37. }
  38. // input interface - columnKey and indexKey
  39. inValue := reflect.ValueOf(input)
  40. inPrtEValue, inType := indirectSimple(inValue)
  41. inElemKind, inKeyType, inElemType := columnElemType(inPrtEValue, inType, columnKey, indexKey)
  42. if inElemKind == reflect.Struct && ((columnKey != "" && !isFirstLetterUp(columnKey)) ||
  43. (indexKey != "" && !isFirstLetterUp(indexKey))) {
  44. panic("columnKey or indexKey must be public field")
  45. }
  46. // no relation with pkg_path
  47. if inKeyType != dKeyType {
  48. panic("'dest' key type does not consist with 'input[indexKey]' type")
  49. }
  50. // no relation with pkg_path
  51. if inElemType != dElemType {
  52. panic("'dest' elem type does not consist with 'input[columnKey]' type")
  53. }
  54. // data operation
  55. dValueElem := ptrToElem(dValue)
  56. var tempKey, tempColumn reflect.Value
  57. switch inValue.Kind() {
  58. case reflect.Slice, reflect.Array:
  59. for i := 0; i < inValue.Len(); i++ {
  60. tempColumn = inValue.Index(i)
  61. if inElemKind == reflect.Struct {
  62. if indexKey != "" {
  63. tempKey = tempColumn.FieldByName(indexKey)
  64. }
  65. if columnKey != "" {
  66. tempColumn = tempColumn.FieldByName(columnKey)
  67. }
  68. } else {
  69. if indexKey != "" {
  70. tempKey = tempColumn.MapIndex(reflect.ValueOf(indexKey))
  71. }
  72. if columnKey != "" {
  73. tempColumn = tempColumn.MapIndex(reflect.ValueOf(columnKey))
  74. }
  75. }
  76. dValueElem = columnSetValue(dType, dValueElem, tempColumn, tempKey)
  77. }
  78. case reflect.Map:
  79. for _, k := range inValue.MapKeys() {
  80. tempColumn = inValue.MapIndex(k)
  81. if inElemKind == reflect.Struct {
  82. if indexKey != "" {
  83. tempKey = tempColumn.FieldByName(indexKey)
  84. }
  85. if columnKey != "" {
  86. tempColumn = tempColumn.FieldByName(columnKey)
  87. }
  88. } else {
  89. if indexKey != "" {
  90. tempKey = tempColumn.MapIndex(reflect.ValueOf(indexKey))
  91. }
  92. if columnKey != "" {
  93. tempColumn = tempColumn.MapIndex(reflect.ValueOf(columnKey))
  94. }
  95. }
  96. dValueElem = columnSetValue(dType, dValueElem, tempColumn, tempKey)
  97. }
  98. }
  99. // set elem data
  100. dValue.Elem().Set(dValueElem)
  101. }
  102. // columnSetValue set column elem data
  103. func columnSetValue(rKind reflect.Kind, rv, column, key reflect.Value) reflect.Value {
  104. switch rKind {
  105. case reflect.Slice, reflect.Array:
  106. rv = reflect.Append(rv, column)
  107. case reflect.Map:
  108. if rv.IsNil() {
  109. panic("columnSetValue: reflect.Value is nil")
  110. }
  111. rv.SetMapIndex(key, column)
  112. }
  113. return rv
  114. }
  115. // columnElemType analysis column type and index type
  116. func columnElemType(rv reflect.Value, rt reflect.Type, columnKey, indexKey string) (reflect.Kind, string, string) {
  117. var err error
  118. var elemKind reflect.Kind
  119. var keyType, elemType string
  120. switch rv.Kind() {
  121. case reflect.Slice, reflect.Array, reflect.Map:
  122. // indexKey operation
  123. if indexKey == "" {
  124. keyType = reflect.Int.String()
  125. } else {
  126. elemKind, keyType, err = fieldElemType(rt.Elem(), indexKey)
  127. if err != nil {
  128. panic(err.Error())
  129. }
  130. }
  131. // columnKey operation
  132. if columnKey == "" {
  133. elemType = rt.Elem().String()
  134. } else {
  135. elemKind, elemType, err = fieldElemType(rt.Elem(), columnKey)
  136. if err != nil {
  137. panic(err.Error())
  138. }
  139. }
  140. default:
  141. panic("haystack: v type must be slice, array or map")
  142. }
  143. return elemKind, keyType, elemType
  144. }
  145. // fieldElemType analysis field type
  146. func fieldElemType(elemRt reflect.Type, key string) (reflect.Kind, string, error) {
  147. var err error
  148. var elemType string
  149. elemKind := elemRt.Kind()
  150. switch elemKind {
  151. case reflect.Struct:
  152. field, isExist := elemRt.FieldByName(key)
  153. if !isExist {
  154. err = errors.New(fmt.Sprintf("input map has no column[%s]", key))
  155. return elemKind, elemType, err
  156. }
  157. elemType = field.Type.String()
  158. case reflect.Map:
  159. elemType = elemRt.Elem().String()
  160. default:
  161. panic("haystack: elemRt type must be map or struct")
  162. }
  163. return elemKind, elemType, err
  164. }
  165. // set operation type
  166. type setOps bool
  167. const (
  168. // set operation
  169. instOps setOps = true
  170. diffOps setOps = false
  171. // constant data
  172. uniqueOps bool = false
  173. )
  174. // Diff array Diff to d
  175. // php array_diff
  176. func Diff(d interface{}, dArr ...interface{}) {
  177. // d interface
  178. dValue := reflect.ValueOf(d)
  179. if dValue.Kind() != reflect.Ptr || dValue.IsNil() {
  180. panic(fmt.Sprintf("haystack: d type[%T] error", reflect.TypeOf(dValue)))
  181. }
  182. // array diff
  183. diffValue := operateSetValue(dValue, diffOps, dArr...)
  184. // set elem data
  185. dValue.Elem().Set(diffValue)
  186. }
  187. // Intersect array Intersect to d
  188. // php array_intersect
  189. func Intersect(d interface{}, dArr ...interface{}) {
  190. // d interface indirectForArr
  191. dValue := reflect.ValueOf(d)
  192. if dValue.Kind() != reflect.Ptr || dValue.IsNil() {
  193. panic(fmt.Sprintf("haystack: d type[%T] error", reflect.TypeOf(dValue)))
  194. }
  195. // array intersect
  196. instValue := operateSetValue(dValue, instOps, dArr...)
  197. // set elem data
  198. dValue.Elem().Set(instValue)
  199. }
  200. // operateSetValue operation set_value
  201. func operateSetValue(dv reflect.Value, ops setOps, dArr ...interface{}) reflect.Value {
  202. // check dValue
  203. if dv.Kind() == reflect.Ptr {
  204. dv = dv.Elem()
  205. }
  206. // operation set
  207. var newValue reflect.Value
  208. dType, _ := indirect(dv)
  209. indirectStr := reflect.Indirect(dv)
  210. for _, arr := range dArr {
  211. // type compare
  212. arrValue := reflect.ValueOf(arr)
  213. if arrValue.Kind() == reflect.Ptr && arrValue.IsNil() {
  214. continue
  215. }
  216. // new data
  217. switch dType {
  218. case reflect.Slice, reflect.Array:
  219. newValue = reflect.MakeSlice(indirectStr.Type(), 0, dv.Len())
  220. for i := 0; i < dv.Len(); i++ {
  221. if inByRValue(dv.Index(i), arrValue) == bool(ops) {
  222. newValue = reflect.Append(newValue, dv.Index(i))
  223. }
  224. }
  225. case reflect.Map:
  226. newValue = reflect.MakeMap(indirectStr.Type())
  227. for _, k := range dv.MapKeys() {
  228. if inByRValue(dv.MapIndex(k), arrValue) == bool(ops) {
  229. newValue.SetMapIndex(k, dv.MapIndex(k))
  230. }
  231. }
  232. }
  233. // set elem data
  234. dv.Set(newValue)
  235. }
  236. return dv
  237. }
  238. // In check d is in 'arr'
  239. // php in_array
  240. func In(d interface{}, arr interface{}) bool {
  241. dValue := reflect.ValueOf(d)
  242. arrValue := reflect.ValueOf(arr)
  243. return inByRValue(dValue, arrValue)
  244. }
  245. // inByRValue in data by reflect value
  246. func inByRValue(dV reflect.Value, arrV reflect.Value) bool {
  247. dVKind, dvType := indirect(dV)
  248. arrType, arrElemType, _ := indirectForArr(arrV)
  249. if dvType != arrElemType {
  250. // d does not consist with arr elem
  251. return false
  252. }
  253. isExist := false
  254. switch dVKind {
  255. case reflect.Map, reflect.Array, reflect.Slice, reflect.Struct:
  256. isExist = inDeepEqual(dV, arrV, arrType)
  257. default:
  258. isExist = inEqual(dV, arrV, arrType)
  259. }
  260. return isExist
  261. }
  262. // inEqual use array simple data equal
  263. func inEqual(dV reflect.Value, arrV reflect.Value, arrT reflect.Kind) bool {
  264. isExist := false
  265. dV = ptrToElem(dV) // check ptr
  266. arrV = ptrToElem(arrV) // check ptr
  267. switch arrT {
  268. case reflect.Slice, reflect.Array:
  269. for i := 0; i < arrV.Len(); i++ {
  270. if isExist = dV.Interface() == arrV.Index(i).Interface(); isExist {
  271. break
  272. }
  273. }
  274. case reflect.Map:
  275. for _, k := range arrV.MapKeys() {
  276. if isExist = dV.Interface() == arrV.MapIndex(k).Interface(); isExist {
  277. break
  278. }
  279. }
  280. default:
  281. panic("haystack: arrV type must be slice, array or map")
  282. }
  283. return isExist
  284. }
  285. // inDeepEqual use array complex data equal
  286. func inDeepEqual(dV reflect.Value, arrV reflect.Value, arrT reflect.Kind) bool {
  287. isExist := false
  288. dV = ptrToElem(dV) // check ptr
  289. arrV = ptrToElem(arrV) // check ptr
  290. switch arrT {
  291. case reflect.Slice, reflect.Array:
  292. for i := 0; i < arrV.Len(); i++ {
  293. if isExist = reflect.DeepEqual(dV.Interface(), arrV.Index(i).Interface()); isExist {
  294. break
  295. }
  296. }
  297. case reflect.Map:
  298. for _, k := range arrV.MapKeys() {
  299. if isExist = reflect.DeepEqual(dV.Interface(), arrV.MapIndex(k).Interface()); isExist {
  300. break
  301. }
  302. }
  303. default:
  304. panic("haystack: d type must be slice, array or map")
  305. }
  306. return isExist
  307. }
  308. // Merge array merge to d
  309. // php array_merge
  310. func Merge(d interface{}, dArr ...interface{}) {
  311. // d interface indirectForArr
  312. dValue := reflect.ValueOf(d)
  313. if dValue.Kind() != reflect.Ptr || dValue.IsNil() {
  314. panic(fmt.Sprintf("haystack: d type[%T] error", reflect.TypeOf(dValue)))
  315. }
  316. // array merge
  317. dValueElem := ptrToElem(dValue)
  318. dType, dElemType, dKeyType := indirectForArr(dValue)
  319. for _, arr := range dArr {
  320. // type compare
  321. arrValue := reflect.ValueOf(arr)
  322. if dValue.Kind() != reflect.Ptr || dValue.IsNil() {
  323. continue
  324. }
  325. arrType, arrElemType, arrKeyType := indirectForArr(arrValue)
  326. if arrType != dType {
  327. panic("'dArr' type does not consist with 'd' type")
  328. }
  329. if arrElemType != dElemType {
  330. panic("'dArr' elem type does not consist with 'd' elem type")
  331. }
  332. if dKeyType != arrKeyType {
  333. panic("'dArr' key type does not consist with 'd' key type")
  334. }
  335. // data merge
  336. arrValue = ptrToElem(arrValue)
  337. switch dType {
  338. case reflect.Slice, reflect.Array:
  339. for i := 0; i < arrValue.Len(); i++ {
  340. dValueElem = reflect.Append(dValueElem, arrValue.Index(i))
  341. }
  342. case reflect.Map:
  343. for _, k := range arrValue.MapKeys() {
  344. dValueElem.SetMapIndex(k, arrValue.MapIndex(k))
  345. }
  346. default:
  347. panic("haystack: d type must be slice, array or map")
  348. }
  349. }
  350. // set elem data
  351. dValue.Elem().Set(dValueElem)
  352. }
  353. // Values get array values
  354. // php array_values
  355. func Values(d interface{}, values interface{}) {
  356. // values interface indirectForArr
  357. vValue := reflect.ValueOf(values)
  358. if vValue.Kind() != reflect.Ptr || vValue.IsNil() {
  359. panic(fmt.Sprintf("haystack: values type[%T] error", reflect.TypeOf(vValue)))
  360. }
  361. vType, vElemType, _ := indirectForArr(vValue)
  362. if vType != reflect.Slice && vType != reflect.Array {
  363. panic("haystack: values type must be slice or array")
  364. }
  365. // d interface indirectForArr
  366. dValue := reflect.ValueOf(d)
  367. dType, dElemType, _ := indirectForArr(dValue)
  368. if vElemType != dElemType {
  369. panic("'d' key type does not consist with 'keys' elem type")
  370. }
  371. vValueElem := ptrToElem(vValue)
  372. switch dType {
  373. case reflect.Slice, reflect.Array:
  374. for i := 0; i < dValue.Len(); i++ {
  375. vValueElem = reflect.Append(vValueElem, dValue.Index(i))
  376. }
  377. case reflect.Map:
  378. for _, k := range dValue.MapKeys() {
  379. vValueElem = reflect.Append(vValueElem, dValue.MapIndex(k))
  380. }
  381. default:
  382. panic("haystack: d type must be slice, array or map")
  383. }
  384. // set elem data
  385. vValue.Elem().Set(vValueElem)
  386. }
  387. // Keys get array keys
  388. // php array_keys
  389. func Keys(d interface{}, keys interface{}) {
  390. // keys interface indirectForArr
  391. keysValue := reflect.ValueOf(keys)
  392. if keysValue.Kind() != reflect.Ptr || keysValue.IsNil() {
  393. panic(fmt.Sprintf("haystack: keys type[%T] error", reflect.TypeOf(keysValue)))
  394. }
  395. keysType, keysElemType, _ := indirectForArr(keysValue)
  396. if keysType != reflect.Slice && keysType != reflect.Array {
  397. panic("haystack: keys type must be slice or array")
  398. }
  399. // d interface indirectForArr
  400. dValue := reflect.ValueOf(d)
  401. dType, _, dKeyType := indirectForArr(dValue)
  402. if keysElemType != dKeyType {
  403. panic("'keys' key type does not consist with 'd' elem type")
  404. }
  405. keysElem := ptrToElem(keysValue)
  406. switch dType {
  407. case reflect.Slice, reflect.Array:
  408. for i := 0; i < dValue.Len(); i++ {
  409. keysElem = reflect.Append(keysElem, reflect.ValueOf(i))
  410. }
  411. case reflect.Map:
  412. for _, k := range dValue.MapKeys() {
  413. keysElem = reflect.Append(keysElem, k)
  414. }
  415. default:
  416. panic("haystack: d type must be slice, array or map")
  417. }
  418. // set elem data
  419. keysValue.Elem().Set(keysElem)
  420. }
  421. // Unique array data de-duplication
  422. // php array_unique
  423. func Unique(d interface{}) {
  424. // d interface indirectForArr
  425. dv := reflect.ValueOf(d)
  426. if dv.Kind() != reflect.Ptr || dv.IsNil() {
  427. panic(fmt.Sprintf("haystack: d type[%T] error", reflect.TypeOf(dv)))
  428. }
  429. dvElem := ptrToElem(dv)
  430. // unique operation
  431. var newValue reflect.Value
  432. dType, _ := indirect(dv)
  433. indirectStr := reflect.Indirect(dv)
  434. switch dType {
  435. case reflect.Slice, reflect.Array:
  436. newValue = reflect.MakeSlice(indirectStr.Type(), 0, dvElem.Len())
  437. for i := 0; i < dvElem.Len(); i++ {
  438. if inByRValue(dvElem.Index(i), newValue) == uniqueOps {
  439. newValue = reflect.Append(newValue, dvElem.Index(i))
  440. }
  441. }
  442. case reflect.Map:
  443. newValue = reflect.MakeMap(indirectStr.Type())
  444. for _, k := range dvElem.MapKeys() {
  445. if inByRValue(dvElem.MapIndex(k), newValue) == uniqueOps {
  446. newValue.SetMapIndex(k, dvElem.MapIndex(k))
  447. }
  448. }
  449. }
  450. // set elem data
  451. dv.Elem().Set(newValue)
  452. }
  453. // indirect get interface kind and type
  454. func indirect(rv reflect.Value) (reflect.Kind, string) {
  455. // get reflect value and type
  456. rvValue, rvType := indirectSimple(rv)
  457. return rvValue.Kind(), rvType.String()
  458. }
  459. // indirectForArr get slice, array or map type
  460. func indirectForArr(rv reflect.Value) (reflect.Kind, string, string) {
  461. // get reflect value and type
  462. rvValue, rvType := indirectSimple(rv)
  463. vType := rvValue.Kind()
  464. var vKeyType, vElemType string
  465. switch vType {
  466. case reflect.Slice, reflect.Array:
  467. vKeyType = reflect.Int.String()
  468. vElemType = rvType.Elem().String()
  469. case reflect.Map:
  470. vKeyType = rvType.Key().String()
  471. vElemType = rvType.Elem().String()
  472. default:
  473. panic("haystack: v type must be slice, array or map")
  474. }
  475. return vType, vElemType, vKeyType
  476. }
  477. // indirectSimple indirect_simply
  478. func indirectSimple(rv reflect.Value) (reflect.Value, reflect.Type) {
  479. // check valid
  480. if !rv.IsValid() {
  481. panic("indirectSimple: reflect.Value is nil")
  482. }
  483. // get reflect value and type
  484. var rvValue reflect.Value
  485. var rvType reflect.Type
  486. switch rv.Kind() {
  487. case reflect.Ptr:
  488. rvValue = rv.Elem()
  489. rvType = rv.Type().Elem()
  490. default:
  491. rvValue = rv
  492. rvType = rv.Type()
  493. }
  494. return rvValue, rvType
  495. }
  496. // ptrToElem Ptr to elem
  497. func ptrToElem(v reflect.Value) reflect.Value {
  498. if v.Kind() == reflect.Ptr {
  499. v = v.Elem()
  500. }
  501. return v
  502. }
  503. // isFirstLetterUp the first letter is up
  504. func isFirstLetterUp(s string) bool {
  505. regObj, _ := regexp.Compile("^[A-Z].*")
  506. return regObj.MatchString(s)
  507. }