@onesy/utils
Version:
104 lines (103 loc) • 4.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const is_1 = __importDefault(require("./is"));
const unique_1 = __importDefault(require("./unique"));
const combinationWithRepetition_1 = __importDefault(require("./combinationWithRepetition"));
const optionsDefault = {
response: 'array',
};
// m - array, n - item length
// m! / n!(m - n)!
function combination(value_, items_ = 0, options_ = {}) {
const options = Object.assign(Object.assign({}, optionsDefault), options_);
if ((0, is_1.default)('array', value_)) {
const value = (0, unique_1.default)(value_);
const items = (0, is_1.default)('number', items_) ? items_ : 0;
const length = value.length;
if (items < 1)
return [value];
if (items === 1)
return value.map(item_ => [item_]);
if (items === length)
return [value];
if (items > length)
return (0, combinationWithRepetition_1.default)(value, items, options);
const response = [];
let item = [...Array(items).keys()];
let index = items - 2;
const max = length - items;
let updated = false;
if (options.response === 'array') {
while (index >= 0) {
if (updated) {
index = items - 2;
updated = false;
}
while (item[item.length - 1] < length) {
const item_ = item.slice().map(index_ => value[index_]);
response.push(item_);
item[item.length - 1]++;
}
// Increment index if it item index is less than max + index
// else move on to previous one, etc.
// and all following keys up to items length should be +1 index
while (true) {
if (item[index] === max + index) {
index--;
if (index < 0)
break;
updated = true;
}
else {
// Increment item index
item[index]++;
// and make all following items up to items length previous + 1
const part = item.slice(0, index + 1);
item = [...part, ...Array(items - part.length).fill(0).map((_, i) => item[index] + i + 1)];
break;
}
}
}
return response;
}
if (options.response === 'yield')
return function* () {
while (index >= 0) {
if (updated) {
index = items - 2;
updated = false;
}
while (item[item.length - 1] < length) {
const item_ = item.slice().map(index_ => value[index_]);
yield item_;
response.push(item_);
item[item.length - 1]++;
}
// Increment index if it item index is less than max + index
// else move on to previous one, etc.
// and all following keys up to items length should be +1 index
while (true) {
if (item[index] === max + index) {
index--;
if (index < 0)
break;
updated = true;
}
else {
// Increment item index
item[index]++;
// and make all following items up to items length previous + 1
const part = item.slice(0, index + 1);
item = [...part, ...Array(items - part.length).fill(0).map((_, i) => item[index] + i + 1)];
break;
}
}
}
return response;
};
}
}
exports.default = combination;