-
Notifications
You must be signed in to change notification settings - Fork 3
/
GBEArray.pas
596 lines (524 loc) · 21.5 KB
/
GBEArray.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
{ Developed by Grégory Bersegeay 2022-2024
https://github.com/gbegreg/MapReduce
https://www.gbesoft.fr
https://www.youtube.com/channel/UCmmgsWSi92t51LbWaiyBRkQ
}
unit GBEArray;
interface
uses System.SysUtils, Generics.Collections, system.Generics.Defaults, system.Threading, System.Rtti, system.Math, StrUtils;
type
TGBEMerge = (subtract, inBoth);
TGBEArray<T> = record
private
Data: TArray<T>; // the datas
public
class function Create(const Source: TArray<T>): TGBEArray<T>; static; // to feed the datas
function Add(aValue : T): integer; // Add a value to the end of the array and return the new length
function Any(Lambda: TPredicate<T>): boolean; // any : is there at least one element that corresponds to the request
function Concat(anArray: TGBEArray<T>): TGBEArray<T>; // Concat : concat this TGBEArray<T> with another TGBEArray<T> into a new one
function Every(const Lambda: TPredicate<T>): Boolean; // Each element respects the lambda
function Extract(fromElement : integer = 0; toElement : integer = 0): TGBEArray<T>; // Extract element from an TGBEArray from fromElement indice to toElement indice to a new TGBEArray
// if fromElement or toElement are negative, it's indicate an offset from the end of the TGBEArray
function Fill(aValue : T; iStart : integer = 0; iEnd : integer = -1): TGBEArray<T>; // Fill an TGBEArray<T> with aValue. If the TGBEArray is empty and the iStart at 0, then iEnd parameter specify also the length of the TGBEArray<T>
function Filter(Lambda: TPredicate<T>): TGBEArray<T>; // filter
function FilterEvenItems(Lambda: TPredicate<T>): TGBEArray<T>; // filter on even items only
function FilterOddItems(Lambda: TPredicate<T>): TGBEArray<T>; // filter on odd items only
function FindIndex(Lambda: TPredicate<T>):integer; // Return first index of element that match with the predicate
function FirstOrDefault(const Lambda: TPredicate<T> = nil): T; // Return first element or first element from a predicate (if predicate set) or the default value of T
procedure ForEach(Lambda: TProc<T>; fromElement : integer = 0; toElement : integer = -1); // execute lambda for all elements don't return object
function Gather(Lambda: TFunc<T,string, string>; sep : string = ';'): TGBEArray<string>; // group the keys/values and return a TGBEArray<string>
function Includes(aValue: T; lambda: TFunc<T, string> = nil): boolean; // aValue is included in the array ?
function Insert(aValue : T; index : integer = 0): TGBEArray<T>; // Insert aValue at index position and return a new TGBEArray
function IntersectionWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>; // Return a new TGBEArray which is intersection of original arrya and anotherArray
function Join(sep: string = ','; lambda: TFunc<T, string> = nil): String; // Join elements of array in a string with sep as separator
function KeepDuplicates: TGBEArray<T>; // Return a new TGBEArray with only duplicates elements
function LastOrDefault(const Lambda: TPredicate<T> = nil): T; // Return first element or first element from a predicate (if predicate set) or the default value of T
function Map<S>(Lambda: TFunc<T, S>): TGBEArray<S>; // map
function MapParallel<S>(Lambda: TFunc<T, S>): TGBEArray<S>; // mapParallel
function AbsoluteMajorityElement(Lambda: TFunc<T, String> = nil;
noAbsoluteMajority : string = 'No absolute majority'): String; // returns a string which indicates the element of the array which is present in an absolute majority, returns noAbsoluteMajority if no element has an absolute majority
function Pop:T; // return the last item of the array and remove it from the array
function Print(Lambda: TFunc<T, T>): TGBEArray<T>; // print the data
function Reduce<S>(Lambda: TFunc<S, T, S>; const Init: S): S; // reduce
function ReduceRight<S>(Lambda: TFunc<S, T, S>; const Init: S): S;
function Remove(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>; // return a new TGBEArray<T> without element of anotherArray
function Reverse:TGBEArray<T>; // Reverse the array
function Shift: T; // return the first item of the array and remove it from the array
function Swap(index1, index2 : integer): TGBEArray<T>; // Return new TGBEArra<T> with swap item1 and item2
function Sort(const Comparer: IComparer<T> = nil): TGBEArray<T>; // sort
function ParallelSort(const Comparer: IComparer<T> = nil): TGBEArray<T>; // sort with TParallelArray
function SuchAs(index : integer; aValue : T): TGBEArray<T>; // Generate a new Array with the same datas but with aValue at index position
function SymmetricalDifferenceWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>; // Return a new TGBEArray<T> symetrical difference of original array and anotherArray
function ToArray: TArray<T>; // convert TGBEArry to TArray
function ToDictionary(iStartKey : integer = 0): TDictionary<integer, T>; // convert to TDictionary with an optional paramter to specify the start index of key
function ToString(Lambda: TFunc<T, String>; sep : string = ','): String; // convert to string
function UnionWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>; // Return a new TGBEArray<T> which is union between original array and anotherArray
function Unique(const Comparer: IComparer<T> = nil): TGBEArray<T>; // Return a new TGBEArray<T> without duplicates. You can specify a comparer to sort result array as you want
end;
implementation
function TGBEArray<T>.Concat(anArray: TGBEArray<T>): TGBEArray<T>;
begin
var ResultArray: TArray<T>;
var iResultArray := 0;
SetLength(ResultArray, length(self.Data) + length(anArray.Data));
for var it in Self.Data do begin
ResultArray[iResultArray] := it;
inc(iResultArray)
end;
for var it in anArray.Data do begin
ResultArray[iResultArray] := it;
inc(iResultArray)
end;
result := TGBEArray<T>.Create(ResultArray);
end;
class function TGBEArray<T>.Create(const Source: TArray<T>): TGBEArray<T>;
begin
Result.Data := Source;
end;
function TGBEArray<T>.Add(aValue: T): integer;
begin
var lg := length(self.Data) +1;
SetLength(self.Data, lg);
self.Data[lg-1] := aValue;
result := lg;
end;
function TGBEArray<T>.Fill(aValue: T; iStart : integer = 0; iEnd : integer = -1): TGBEArray<T>;
begin
if length(self.Data) = 0 then begin
if iEnd > -1 then begin
SetLength(self.Data, iEnd);
dec(iEnd);
end;
end;
if (iEnd = -1) or (iEnd > length(self.Data)) then iEnd := length(self.Data)-1;
for var i := iStart to iEnd do begin
self.Data[i] := aValue;
end;
result := self;
end;
function TGBEArray<T>.Filter(Lambda: TPredicate<T>): TGBEArray<T>;
begin
var ResultArray: TArray<T>;
var ResultArrayFinalLength := 0;
SetLength(ResultArray,length(self.Data));
for var it in Self.Data do begin
if Lambda(it) then begin
ResultArray[ResultArrayFinalLength] := it;
inc(ResultArrayFinalLength);
end;
end;
SetLength(ResultArray,ResultArrayFinalLength);
result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.FilterOddItems(Lambda: TPredicate<T>): TGBEArray<T>;
begin
var ResultArray : TArray<T>;
var ResultArrayFinalLength := 0;
SetLength(ResultArray,length(self.Data));
for var i := 1 to length(Self.Data) do begin
if odd(i) then begin
ResultArray[ResultArrayFinalLength] := Self.Data[i-1];
inc(ResultArrayFinalLength);
end;
end;
SetLength(ResultArray,ResultArrayFinalLength);
result := TGBEArray<T>.Create(ResultArray).Filter(lambda);
end;
function TGBEArray<T>.FilterEvenItems(Lambda: TPredicate<T>): TGBEArray<T>;
begin
var ResultArray : TArray<T>;
var ResultArrayFinalLength := 0;
SetLength(ResultArray,length(self.Data));
for var i := 1 to length(Self.Data) do begin
if not(odd(i)) then begin
ResultArray[ResultArrayFinalLength] := Self.Data[i-1];
inc(ResultArrayFinalLength);
end;
end;
SetLength(ResultArray,ResultArrayFinalLength);
result := TGBEArray<T>.Create(ResultArray).Filter(lambda);
end;
function TGBEArray<T>.FindIndex(Lambda: TPredicate<T>): integer;
begin
var indice := -1;
for var it in self.Data do begin
inc(indice);
if Lambda(it) then exit(indice);
end;
exit(-1);
end;
procedure TGBEArray<T>.ForEach(Lambda: TProc<T>; fromElement : integer = 0; toElement : integer = -1);
begin
var max := length(self.Data) -1;
if (toElement > fromElement) and (toElement <= max) then max := toElement;
for var it := fromElement to max do
Lambda(self.Data[it]);
end;
function TGBEArray<T>.Gather(Lambda: TFunc<T, string, string>; sep : string = ';'): TGBEArray<string>;
begin
var aDico := TDictionary<String,String>.create;
var ResultArray: TArray<string>;
SetLength(ResultArray,length(self.Data));
var iResultArray := 0;
for var it in self.Data do begin
ResultArray[iResultArray] := Lambda(it, sep);
inc(iResultArray);
end;
var valeurExistante := '';
for var it in ResultArray do begin
var cle := it.Substring(0,pos(sep,it)-1);
var valeur := it.Substring(pos(sep,it));
if aDico.TryGetValue(cle,valeurExistante) then
aDico.AddOrSetValue(cle, valeurExistante+' '+valeur)
else aDico.Add(cle, valeur);
end;
SetLength(ResultArray, aDico.Count);
iResultArray := 0;
for var it in aDico.Keys do begin
ResultArray[iResultArray] := it + sep + aDico.Items[it];
inc(iResultArray);
end;
result := TGBEArray<string>.Create(ResultArray);
end;
function TGBEArray<T>.Insert(aValue: T; index: integer): TGBEArray<T>;
begin
if index <= length(self.Data) then begin
var ResultArray: TArray<T>;
var iResultArray := 0;
SetLength(ResultArray,length(self.Data)+1);
var insere := false;
for var i := 0 to length(self.Data) do begin
if i = index then begin
ResultArray[iResultArray] := aValue;
insere := true;
end else begin
if insere then ResultArray[iResultArray] := self.Data[i-1]
else ResultArray[iResultArray] := self.Data[i];
end;
inc(iResultArray);
end;
result := TGBEArray<T>.Create(ResultArray);
end else result := TGBEArray<T>.Create(self.data);
end;
function TGBEArray<T>.KeepDuplicates: TGBEArray<T>;
begin
var hash1 := TDictionary<T, integer>.create(length(self.Data));
var hash2 := TDictionary<T, integer>.create(length(self.Data));
var lgHash1 := hash1.Count;
var lgHash2 := hash2.Count;
try
for var it in self.Data do begin
lgHash1 := hash1.Count;
hash1.AddOrSetValue(it, 0);
if lgHash1 = hash1.count then begin
lgHash2 := hash2.Count;
hash2.AddOrSetValue(it, 0);
end;
end;
var ResultArray: TArray<T>;
SetLength(ResultArray, hash2.Count);
resultArray := hash2.Keys.ToArray;
result := TGBEArray<T>.Create(ResultArray);
finally
hash1.Free;
hash2.Free;
end;
end;
function TGBEArray<T>.LastOrDefault(const Lambda: TPredicate<T>): T;
begin
if assigned(lambda) then begin
var indice := 0;
for var i := length(Self.Data)-1 downto 0 do
if Lambda(Self.Data[i]) then Exit(Self.Data[i]);
Exit(Default(T));
end else begin
if (Length(Self.Data) > 0) then Exit(Self.Data[length(Self.Data)-1])
else Exit(Default(T));
end;
end;
function TGBEArray<T>.Map<S>(Lambda: TFunc<T, S>): TGBEArray<S>;
begin
var ResultArray: TArray<S>;
var iResultArray := 0;
SetLength(ResultArray,length(self.Data));
for var it in self.Data do begin
ResultArray[iResultArray] := Lambda(it);
inc(iResultArray);
end;
result := TGBEArray<S>.Create(ResultArray);
end;
function TGBEArray<T>.MapParallel<S>(Lambda: TFunc<T, S>): TGBEArray<S>;
begin
var ResultArray: TArray<S>;
var iResultArray := 0;
SetLength(ResultArray,length(self.Data));
var anArray := self.Data;
TParallel.For(0, length(anArray)-1,
procedure (I:Integer)
begin
ResultArray[i] := Lambda(anArray[i]);
end
);
result := TGBEArray<S>.Create(ResultArray);
end;
function TGBEArray<T>.Pop: T;
begin
result := self.Data[length(self.Data)-1];
SetLength(self.Data,length(self.Data)-1);
end;
function TGBEArray<T>.Shift: T;
begin
result := self.Data[0];
var ResultArray: TArray<T>;
SetLength(ResultArray,length(self.Data)-1);
var indice := 0;
for var i := 1 to length(self.Data)-1 do begin
ResultArray[indice] := self.Data[i];
inc(indice);
end;
setLength(Self.Data, length(ResultArray));
Self.Data := Copy(ResultArray);
end;
function TGBEArray<T>.Print(Lambda: TFunc<T, T>): TGBEArray<T>;
begin
for var it: T in self.Data do
Lambda(it);
result := TGBEArray<T>(self.Data);
end;
function TGBEArray<T>.Any(Lambda: TPredicate<T>): boolean;
begin
for var it in Self.Data do
if Lambda(it) then Exit(True);
Exit(False);
end;
function TGBEArray<T>.Sort(const Comparer: IComparer<T> = nil): TGBEArray<T>;
begin
var ResultArray : TArray<T> := Copy(Self.Data);
if assigned(Comparer) then TArray.Sort<T>(ResultArray, Comparer)
else TArray.Sort<T>(ResultArray);
Result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.ParallelSort(const Comparer: IComparer<T> = nil): TGBEArray<T>;
begin
var ResultArray : TArray<T> := Copy(Self.Data);
if assigned(Comparer) then TParallelArray.Sort<T>(ResultArray, Comparer)
else TParallelArray.Sort<T>(ResultArray);
Result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.SuchAs(index: integer; aValue: T): TGBEArray<T>;
begin
var ResultArray: TArray<T>;
var iResultArray := 0;
SetLength(ResultArray,length(self.Data));
for var it in self.Data do begin
if iResultArray = index then ResultArray[iResultArray] := aValue
else ResultArray[iResultArray] := it;
inc(iResultArray);
end;
result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.Swap(index1, index2: integer): TGBEArray<T>;
begin
var ResultArray : TArray<T> := Copy(Self.Data);
SetLength(ResultArray,length(self.Data));
if (index1 < length(self.Data)) and (index2 < length(self.Data)) then begin
var temp := resultArray[index1];
ResultArray[index1] := ResultArray[index2];
ResultArray[index2] := temp;
end;
result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.Reduce<S>(Lambda: TFunc<S, T, S>; const Init: S): S;
begin
result := Init;
for var it in Self.Data do
result := Lambda(result, it);
end;
function TGBEArray<T>.ReduceRight<S>(Lambda: TFunc<S, T, S>; const Init: S): S;
begin
var ResultArray : TGBEArray<T> := TGBEArray<T>.Create(Copy(Self.Data)).Reverse;
result := Init;
for var it in ResultArray.Data do
result := Lambda(result, it);
end;
function TGBEArray<T>.Reverse: TGBEArray<T>;
begin
var ResultArray: TArray<T>;
SetLength(ResultArray,length(self.Data));
var indice := 0;
for var i := length(self.Data) -1 downto 0 do begin
ResultArray[indice] := self.Data[i];
inc(indice);
end;
result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.ToArray: TArray<T>;
begin
result := Self.Data;
end;
function TGBEArray<T>.ToDictionary(iStartKey : integer = 0): TDictionary<integer, T>;
begin
var resultat := TDictionary<integer, T>.create;
var i := iStartKey;
for var it: T in self.Data do begin
resultat.add(i, it);
inc(i);
end;
result := resultat;
end;
function TGBEArray<T>.toString(Lambda: TFunc<T, String>; sep : string = ','): String;
begin
var s := '';
for var it: T in self.Data do begin
if s.IsEmpty then s := Lambda(it)
else s := s + sep + Lambda(it);
end;
result := s;
end;
function TGBEArray<T>.Unique(const Comparer: IComparer<T> = nil): TGBEArray<T>;
begin
var hash := TDictionary<T, integer>.create(length(self.Data));
try
for var it in self.Data do
hash.AddOrSetValue(it, 0);
var ResultArray: TArray<T>;
SetLength(ResultArray, hash.Count);
resultArray := hash.Keys.ToArray;
if assigned(Comparer) then TParallelArray.Sort<T>(resultArray, Comparer);
result := TGBEArray<T>.Create(ResultArray);
finally
hash.Free;
end;
end;
function TGBEArray<T>.FirstOrDefault(const Lambda: TPredicate<T> = nil): T;
begin
if assigned(lambda) then begin
for var X in Self.Data do
if Lambda(X) then Exit(X);
Exit(Default(T));
end else begin
if (Length(Self.Data) > 0) then Exit(Self.Data[0])
else Exit(Default(T));
end;
end;
function TGBEArray<T>.Every(const Lambda: TPredicate<T>): Boolean;
begin
for var X in Self.Data do
if not Lambda(X) then
Exit(False);
Exit(True);
end;
function TGBEArray<T>.Extract(fromElement : integer = 0; toElement : integer = 0): TGBEArray<T>;
begin
var ResultArray: TArray<T>;
var ResultArrayFinalLength := 0;
SetLength(ResultArray,length(self.Data));
var start := fromElement;
if start < 0 then start := length(Self.Data) + start;
var max := toElement;
if toElement < 0 then max := length(Self.Data) + max;
if max < start then max := length(Self.Data) -1;
if toElement = 0 then max := length(Self.Data) -1;
for var i := start to max do begin
ResultArray[ResultArrayFinalLength] := Self.Data[i];
inc(ResultArrayFinalLength);
end;
SetLength(ResultArray,ResultArrayFinalLength);
result := TGBEArray<T>.Create(ResultArray);
end;
function TGBEArray<T>.Join(sep: string = ','; lambda: TFunc<T, string> = nil): String;
begin
var resultat := '';
if assigned(lambda) then begin
for var it in self.Data do
resultat := resultat + sep + lambda(it);
end else begin
for var i := 0 to length(self.Data) -1 do begin
resultat := resultat + TValue.From<T>(self.Data[i]).ToString() + sep;
end;
end;
if resultat.EndsWith(sep, true) then begin
resultat := copy(resultat, 1, length(resultat) - length(sep));
end;
result := resultat;
end;
function TGBEArray<T>.Remove(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>;
begin
result := self.filter(function(value: T): Boolean
begin
result := not(anotherArray.includes(value, lambda));
end);
end;
function TGBEArray<T>.IntersectionWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>;
begin
result := self.filter(function(value: T): Boolean
begin
result := anotherArray.includes(value, lambda);
end);
end;
function TGBEArray<T>.SymmetricalDifferenceWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>;
begin
var courant := TGBEArray<T>.Create(Self.Data);
result := self.filter(function(value: T): Boolean
begin
result := not(anotherArray.includes(value, lambda));
end)
.concat(anotherArray.filter(function(value: T): Boolean
begin
result := not(courant.includes(value, lambda));
end)
);
end;
function TGBEArray<T>.UnionWith(anotherArray: TGBEArray<T>; lambda: TFunc<T, string> = nil): TGBEArray<T>;
begin
var inter := self.intersectionWith(anotherArray, lambda);
result := self.SymmetricalDifferenceWith(anotherArray, lambda).concat(inter);
end;
function TGBEArray<T>.includes(aValue: T; lambda: TFunc<T, string> = nil): boolean;
begin
if assigned(lambda) then begin
for var it in Self.Data do
if lambda(it) = lambda(aValue) then Exit(True);
Exit(False);
end else begin
for var it in Self.Data do
if TValue.From<T>(it).toString = TValue.From<T>(aValue).toString then Exit(True);
Exit(False);
end;
end;
function TGBEArray<T>.AbsoluteMajorityElement(Lambda: TFunc<T, String> = nil; noAbsoluteMajority : string = 'No absolute majority'): String;
begin
var anArray : TArray<String>;
setLength(anArray, length(self.data));
var lambdaAssigned := assigned(lambda);
if lambdaAssigned then begin
for var i := 0 to length(self.Data) -1 do
anArray[i] := lambda(self.Data[i]);
end else begin
for var i := 0 to length(self.Data) -1 do begin
anArray[i] := TValue.From<T>(self.Data[i]).ToString;
end;
end;
// Boyer-Moore majority vote algo
var element : T;
var counter := 0;
for var i := 0 to length(anArray) -1 do begin
if counter = 0 then begin
element := self.Data[i];
counter := 1;
end else begin
if lambdaAssigned then counter := counter + system.Math.ifthen(lambda(element) = anArray[i], 1, -1)
else counter := counter + system.Math.ifthen(TValue.From<T>(element).toString = anArray[i] , 1, -1);
end;
end;
var foundElement :='';
if lambdaAssigned then foundElement := lambda(element)
else foundElement := TValue.From<T>(element).toString;
// foundElement is it really majority ?
var nbFoundElement := 0;
for var I in anArray do begin
if i = foundElement then inc(nbFoundElement);
end;
result := strutils.IfThen(nbFoundElement > length(anArray) / 2, foundElement, noAbsoluteMajority);
end;
end.