Как равномерно распределить одинаковые строки в списке?

Поддержка
  • Здравствуйте, есть список, в нем к примеру 5 строк "один", 10 строк "два", 15 строк "три". Нужно распределить максимально равномерно, а не случайно, чтобы не было 2 одинаковых строк подряд.
    Что-то вроде этого:
    три
    два
    три
    один
    два
    три
    ...
    Количество разных строк и количество их повторений может быть разным, поэтому вручную распределить не получится.

  • Отсортировать, посчитать количество совпадений и пропорционально распихать.
    А затем всё перемешать :)

  • @Vituskosoy А как пропорционально распихать?

  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    @Vituskosoy А как пропорционально распихать?

    Гуглить по: distribute evenly items in array javascript. Сразу скажу - сложно.

  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    Здравствуйте, есть список, в нем к примеру 5 строк "один", 10 строк "два", 15 строк "три". Нужно распределить максимально равномерно, а не случайно, чтобы не было 2 одинаковых строк подряд.
    Что-то вроде этого:
    три
    два
    три
    один
    два
    три
    ...
    Количество разных строк и количество их повторений может быть разным, поэтому вручную распределить не получится.

    Распарсите строку в массив, затем в цикле помещайте элементы из массива в новый массив. При добавлении читайте последний элемент нового массива и если элемент совпадает с тем, что вы хотите добавить, то пропускайте его и берите следующий

  • @Fox по идее да, но будет не совсем равномерно, например:
    три
    два
    три
    два
    три
    два
    три
    один
    три
    один
    Особенно будет заметно если разных строк будет не 3, а 10-20

  • @Ilgiz

    Оно? Или равномерность не устраивает, так как идут подряд значения?

    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    два
    три
    один
    три
    один
    три
    один
    три
    ge
    три
    
    function distributeEvenly(arr) {
        // Function to get the next index, skipping to enforce even distribution
        function getNextIndex(index, skip, length) {
            return (index + skip) % length;
        }
    
        // Create a map to count the frequency of each element
        const map = arr.reduce((acc, e) => {
            acc[e] = (acc[e] || 0) + 1;
            return acc;
        }, {});
    
        // Sort items by count descending
        const sortedItems = Object.keys(map).sort((a, b) => map[b] - map[a]);
    
        // Calculate the minimum skip distance based on the most frequent item
        const maxCount = map[sortedItems[0]];
        const minSkip = Math.floor(arr.length / maxCount);
    
        // Initialize the result array
        const result = [];
    
        // Distribute items starting from the most frequent
        for (let i = 0; i < sortedItems.length; i++) {
            let count = map[sortedItems[i]];
            let index = i;
            while (count > 0) {
                // Find the next available index
                while (result[index] !== undefined) {
                    index = getNextIndex(index, minSkip, arr.length);
                }
                result[index] = sortedItems[i];
                index = getNextIndex(index, minSkip, arr.length);
                count--;
            }
        }
    
        return result;
    }
    
    const inputArray = [
        'один', 'один', 'один', 'один', 'один',
        'два', 'два', 'два', 'два', 'два', 'два', 'два', 'два', 'два', 'два',
        'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три', 'три',
        'ge', 'gee', 'baba'
    ];
    
    const evenlyDistributedArray = distributeEvenly(inputArray);
    console.log(evenlyDistributedArray.join('\n'));
    
  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    @Fox по идее да, но будет не совсем равномерно, например:
    три
    два
    три
    два
    три
    два
    три
    один
    три
    один
    Особенно будет заметно если разных строк будет не 3, а 10-20

    А какую задачу вы пытаетесь решить вот таким вот способом?

  • @Fox есть товары на маркетплейсе у каждого свой id, нужно накручивать поведенческие факторы для них. И желательно это делать равномерно по всем товарам.

  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    @Fox есть товары на маркетплейсе у каждого свой id

    Id в каком виде? Дай пример.

  • @sergerdn Судя по результату это то что предложил Fox, в этом случае строки кучкуются - три и два, потом три и один, не совсем подходит(

  • @sergerdn id просто цифры - 128546335

  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    @sergerdn id просто цифры - 128546335

    Нужен ли каждый раз разный результат после запуска алгоритма распределения или подойдет статичный?

  • @sergerdn статичный подойдет, но входные данные (сами id, количество этих id) могут изменяться при новом запуске скрипта.

  • @Ilgiz said in Как равномерно распределить одинаковые строки в списке?:

    @sergerdn статичный подойдет, но входные данные (сами id, количество этих id) могут изменяться при новом запуске скрипта.

    Дай входные данные и выходные(желаемый результат), чтобы я не составлял их сам. Пожалуйста, оформи данные в виде массива Javascript.

  • @sergerdn
    Входные:
    let ids = [
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572238509:watercolor painting',
    '1572224807:oil painting',
    '1572224807:oil painting',
    '1572224807:oil painting',
    '1572224807:oil painting',
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    '1530765154:botanical wall art'
    ];

    Выходные типа того:
    let ids = [
    '1530765154:botanical wall art'
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    '1572224807:oil painting',
    '1530765154:botanical wall art'
    '1572238509:watercolor painting',
    '1530765154:botanical wall art'
    ];

  • @Ilgiz

    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    
    function isSameId(item1, item2) {
        return item1.split(':')[0] === item2.split(':')[0];
    }
    
    function shuffleArray(array) {
        let currentIndex = array.length,
            temporaryValue, randomIndex;
    
        // While there remain elements to shuffle...
        while (0 !== currentIndex) {
            // Pick a remaining element...
            randomIndex = Math.floor(Math.random() * currentIndex);
            currentIndex -= 1;
    
            // And swap it with the current element.
            temporaryValue = array[currentIndex];
            array[currentIndex] = array[randomIndex];
            array[randomIndex] = temporaryValue;
        }
    
        return array;
    }
    
    function distributeItems(items) {
        let attempts = 0;
        let maxAttempts = items.length * 10;
    
        // First, shuffle the array to get a random order
        let shuffledItems = shuffleArray(items.slice());
    
        for (let i = 0; i < shuffledItems.length - 1; i++) {
            if (isSameId(shuffledItems[i], shuffledItems[i + 1])) {
                let swapIndex = i + 2;
    
                while (swapIndex < shuffledItems.length && isSameId(shuffledItems[i], shuffledItems[swapIndex])) {
                    swapIndex++;
                }
    
                if (swapIndex < shuffledItems.length) {
                    // Swap the consecutive item with another non-consecutive item
                    let temp = shuffledItems[i + 1];
                    shuffledItems[i + 1] = shuffledItems[swapIndex];
                    shuffledItems[swapIndex] = temp;
                } else {
                    // If we've reached the end, we need to shuffle and start over
                    shuffledItems = shuffleArray(items.slice());
                    i = -1; // Start over from the first element after shuffling
                    attempts++;
                    if (attempts > maxAttempts) {
                        console.warn('Max attempts reached, distribution may not be perfect.');
                        break;
                    }
                }
            }
        }
    
        return shuffledItems;
    }
    
    let ids = [
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art'
    ];
    
    let evenlyDistributedArray = distributeItems(ids);
    
    console.log(evenlyDistributedArray.join('\n'));
    
  • @sergerdn said in Как равномерно распределить одинаковые строки в списке?:

    @Ilgiz

    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572224807:oil painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    1572238509:watercolor painting
    1530765154:botanical wall art
    
    function isSameId(item1, item2) {
        return item1.split(':')[0] === item2.split(':')[0];
    }
    
    function shuffleArray(array) {
        let currentIndex = array.length,
            temporaryValue, randomIndex;
    
        // While there remain elements to shuffle...
        while (0 !== currentIndex) {
            // Pick a remaining element...
            randomIndex = Math.floor(Math.random() * currentIndex);
            currentIndex -= 1;
    
            // And swap it with the current element.
            temporaryValue = array[currentIndex];
            array[currentIndex] = array[randomIndex];
            array[randomIndex] = temporaryValue;
        }
    
        return array;
    }
    
    function distributeItems(items) {
        let attempts = 0;
        let maxAttempts = items.length * 10;
    
        // First, shuffle the array to get a random order
        let shuffledItems = shuffleArray(items.slice());
    
        for (let i = 0; i < shuffledItems.length - 1; i++) {
            if (isSameId(shuffledItems[i], shuffledItems[i + 1])) {
                let swapIndex = i + 2;
    
                while (swapIndex < shuffledItems.length && isSameId(shuffledItems[i], shuffledItems[swapIndex])) {
                    swapIndex++;
                }
    
                if (swapIndex < shuffledItems.length) {
                    // Swap the consecutive item with another non-consecutive item
                    let temp = shuffledItems[i + 1];
                    shuffledItems[i + 1] = shuffledItems[swapIndex];
                    shuffledItems[swapIndex] = temp;
                } else {
                    // If we've reached the end, we need to shuffle and start over
                    shuffledItems = shuffleArray(items.slice());
                    i = -1; // Start over from the first element after shuffling
                    attempts++;
                    if (attempts > maxAttempts) {
                        console.warn('Max attempts reached, distribution may not be perfect.');
                        break;
                    }
                }
            }
        }
    
        return shuffledItems;
    }
    
    let ids = [
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572238509:watercolor painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1572224807:oil painting',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art',
        '1530765154:botanical wall art'
    ];
    
    let evenlyDistributedArray = distributeItems(ids);
    
    console.log(evenlyDistributedArray.join('\n'));
    

    Какую нейронку используете? :D

  • @Fox said in Как равномерно распределить одинаковые строки в списке?:

    Какую нейронку используете? :D

    Думаю, я не использую ничего уникального, а все то же самое, что и остальные.
    Вероятно, просто руки у меня немного другие😃

  • @sergerdn Спасибо, попробую разобраться как это в бас впихнуть)