Skip to content

Commit 50161e4

Browse files
authored
Merge pull request #19 from AlphaQuantJS/dev
Implement and fix Series transform and filtering methods: sort, uniqu…
2 parents 3e81f25 + d8e6f16 commit 50161e4

32 files changed

Lines changed: 2061 additions & 85 deletions
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Between method for Series
3+
* Returns a new Series with values between lower and upper bounds (inclusive)
4+
*/
5+
6+
/**
7+
* Creates a between method for Series
8+
* @returns {Function} - Function to be attached to Series prototype
9+
*/
10+
export function between() {
11+
/**
12+
* Returns a new Series with values between lower and upper bounds (inclusive)
13+
* @param {number} lower - Lower bound
14+
* @param {number} upper - Upper bound
15+
* @param {Object} [options] - Options object
16+
* @param {boolean} [options.inclusive=true] - Whether bounds are inclusive
17+
* @returns {Series} - New Series with filtered values
18+
*/
19+
return function(lower, upper, options = {}) {
20+
const { inclusive = true } = options;
21+
22+
if (lower === undefined || upper === undefined) {
23+
throw new Error('Both lower and upper bounds must be provided');
24+
}
25+
26+
if (lower > upper) {
27+
throw new Error('Lower bound must be less than or equal to upper bound');
28+
}
29+
30+
if (inclusive) {
31+
return this.filter((x) => {
32+
const numX = Number(x);
33+
return !isNaN(numX) && numX >= lower && numX <= upper;
34+
});
35+
} else {
36+
return this.filter((x) => {
37+
const numX = Number(x);
38+
return !isNaN(numX) && numX > lower && numX < upper;
39+
});
40+
}
41+
};
42+
}
43+
44+
/**
45+
* Registers the between method on Series prototype
46+
* @param {Class} Series - Series class to extend
47+
*/
48+
export function register(Series) {
49+
if (!Series.prototype.between) {
50+
Series.prototype.between = between();
51+
}
52+
}
53+
54+
export default between;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Contains method for Series
3+
* Returns a new Series with string values that contain the specified substring
4+
*/
5+
6+
/**
7+
* Creates a contains method for Series
8+
* @returns {Function} - Function to be attached to Series prototype
9+
*/
10+
export function contains() {
11+
/**
12+
* Returns a new Series with string values that contain the specified substring
13+
* @param {string} substring - Substring to search for
14+
* @param {Object} [options] - Options object
15+
* @param {boolean} [options.caseSensitive=true] - Whether the search is case sensitive
16+
* @returns {Series} - New Series with filtered values
17+
*/
18+
return function(substring, options = {}) {
19+
const { caseSensitive = true } = options;
20+
21+
if (substring === undefined || substring === null) {
22+
throw new Error('Substring must be provided');
23+
}
24+
25+
return this.filter((value) => {
26+
if (value === null || value === undefined) {
27+
return false;
28+
}
29+
30+
const strValue = String(value);
31+
32+
if (caseSensitive) {
33+
return strValue.includes(substring);
34+
} else {
35+
return strValue.toLowerCase().includes(substring.toLowerCase());
36+
}
37+
});
38+
};
39+
}
40+
41+
/**
42+
* Registers the contains method on Series prototype
43+
* @param {Class} Series - Series class to extend
44+
*/
45+
export function register(Series) {
46+
if (!Series.prototype.contains) {
47+
Series.prototype.contains = contains();
48+
}
49+
}
50+
51+
export default contains;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* EndsWith method for Series
3+
* Returns a new Series with string values that end with the specified suffix
4+
*/
5+
6+
/**
7+
* Creates an endsWith method for Series
8+
* @returns {Function} - Function to be attached to Series prototype
9+
*/
10+
export function endsWith() {
11+
/**
12+
* Returns a new Series with string values that end with the specified suffix
13+
* @param {string} suffix - Suffix to search for
14+
* @param {Object} [options] - Options object
15+
* @param {boolean} [options.caseSensitive=true] - Whether the search is case sensitive
16+
* @returns {Series} - New Series with filtered values
17+
*/
18+
return function(suffix, options = {}) {
19+
const { caseSensitive = true } = options;
20+
21+
if (suffix === undefined || suffix === null) {
22+
throw new Error('Suffix must be provided');
23+
}
24+
25+
return this.filter((value) => {
26+
if (value === null || value === undefined) {
27+
return false;
28+
}
29+
30+
const strValue = String(value);
31+
32+
if (caseSensitive) {
33+
// В режиме чувствительности к регистру проверяем точное совпадение
34+
return strValue.endsWith(suffix);
35+
} else {
36+
return strValue.toLowerCase().endsWith(suffix.toLowerCase());
37+
}
38+
});
39+
};
40+
}
41+
42+
/**
43+
* Registers the endsWith method on Series prototype
44+
* @param {Class} Series - Series class to extend
45+
*/
46+
export function register(Series) {
47+
if (!Series.prototype.endsWith) {
48+
Series.prototype.endsWith = endsWith();
49+
}
50+
}
51+
52+
export default endsWith;

src/methods/series/filtering/filter.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@
55
* @param {Function} predicate - Function that takes a value and returns true/false
66
* @returns {Series} - New Series with filtered values
77
*/
8-
export const filter = (series, predicate) => {
8+
export function filter(series, predicate) {
99
const values = series.toArray();
1010
const filteredValues = values.filter(predicate);
1111
return new series.constructor(filteredValues);
12-
};
12+
}
1313

1414
/**
1515
* Registers the filter method on Series prototype
1616
* @param {Class} Series - Series class to extend
1717
*/
18-
export const register = (Series) => {
19-
Series.prototype.filter = function(predicate) {
20-
return filter(this, predicate);
21-
};
22-
};
18+
export function register(Series) {
19+
if (!Series.prototype.filter) {
20+
Series.prototype.filter = function(predicate) {
21+
return filter(this, predicate);
22+
};
23+
}
24+
}
2325

2426
export default { filter, register };
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* IsNull method for Series
3+
* Returns a new Series with only null or undefined values
4+
*/
5+
6+
/**
7+
* Creates an isNull method for Series
8+
* @returns {Function} - Function to be attached to Series prototype
9+
*/
10+
export function isNull() {
11+
/**
12+
* Returns a new Series with only null or undefined values
13+
* @returns {Series} - New Series with filtered values
14+
*/
15+
return function() {
16+
return this.filter((x) => x === null || x === undefined);
17+
};
18+
}
19+
20+
/**
21+
* Registers the isNull method on Series prototype
22+
* @param {Class} Series - Series class to extend
23+
*/
24+
export function register(Series) {
25+
if (!Series.prototype.isNull) {
26+
Series.prototype.isNull = isNull();
27+
}
28+
}
29+
30+
export default isNull;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Matches method for Series
3+
* Returns a new Series with string values that match the specified regular expression
4+
*/
5+
6+
/**
7+
* Creates a matches method for Series
8+
* @returns {Function} - Function to be attached to Series prototype
9+
*/
10+
export function matches() {
11+
/**
12+
* Returns a new Series with string values that match the specified regular expression
13+
* @param {RegExp|string} pattern - Regular expression pattern to match
14+
* @param {Object} [options] - Options object
15+
* @param {boolean} [options.flags] - Flags for the RegExp if pattern is a string
16+
* @returns {Series} - New Series with filtered values
17+
*/
18+
return function(pattern, options = {}) {
19+
const { flags = '' } = options;
20+
21+
if (pattern === undefined || pattern === null) {
22+
throw new Error('Regular expression pattern must be provided');
23+
}
24+
25+
// Convert string pattern to RegExp if needed
26+
const regex = pattern instanceof RegExp
27+
? pattern
28+
: new RegExp(pattern, flags);
29+
30+
return this.filter((value) => {
31+
if (value === null || value === undefined) {
32+
return false;
33+
}
34+
35+
const strValue = String(value);
36+
return regex.test(strValue);
37+
});
38+
};
39+
}
40+
41+
/**
42+
* Registers the matches method on Series prototype
43+
* @param {Class} Series - Series class to extend
44+
*/
45+
export function register(Series) {
46+
if (!Series.prototype.matches) {
47+
Series.prototype.matches = matches();
48+
}
49+
}
50+
51+
export default matches;

0 commit comments

Comments
 (0)