d3 js sort error in chrome [duplicate]

Существует обходное решение путем захвата кликов на document.body, а затем проверки целевого объекта.

document.body.addEventListener( 'click', function ( event ) {
  if( event.srcElement.id == 'btnSubmit' ) {
    someFunc();
  };
} );
32
задан Leonardo Amigoni 7 February 2012 в 13:16
поделиться

7 ответов

Разверните свою функцию сортировки, чтобы выглядеть так:

function sortF(ob1,ob2) {
    if (ob1.strength > ob2.strength) {
        return 1;
    } else if (ob1.strength < ob2.strength) { 
        return -1;
    }

    // Else go to the 2nd item
    if (ob1.name < ob2.name) { 
        return -1;
    } else if (ob1.name > ob2.name) {
        return 1
    } else { // nothing to split them
        return 0;
    }
}

Сравнение < и > по строкам - это алфавитное сравнение.

62
ответ дан Matt 19 August 2018 в 04:07
поделиться
  • 1
    Это пролило свет на то, как сортировать по первому имени, а затем по имени. Благодаря! – Mike Lyons 4 September 2014 в 03:38

Эта небольшая функция часто бывает удобной при сортировке по нескольким клавишам:

cmp = function(a, b) {
    if (a > b) return +1;
    if (a < b) return -1;
    return 0;
}

Применить это следующим образом:

array.sort(function(a, b) { 
    return cmp(a.strength,b.strength) || cmp(a.name,b.name)
})

Javascript действительно отсутствует оператор космического корабля Ruby , что делает такие сравнения чрезвычайно элегантными.

35
ответ дан georg 19 August 2018 в 04:07
поделиться
  • 1
    Короткие, сладкие и красивые – Serj Sagan 3 June 2013 в 23:08
  • 2
    cough Оператор космического корабля Perl. – Richard Simões 24 March 2014 в 22:32
  • 3
    Спасибо. Я уже некоторое время искал это ядро ​​знаний ... Я просто не знал, как это сказать. Особенно оператор космического корабля. – Joachim Brandon LeBlanc 24 March 2017 в 21:33
  • 4
    Полюбите это, внедренное в приложение. Будет ли это работать с 3 ключами? Я еще не там, но может понадобиться третья сортировка. – Andy Smith 14 August 2018 в 05:44
  • 5
    @AndySmith: конечно, cmp(a, b) || cmp(c, d) || cmp(e, f) и т. Д. И т. Д. И т. Д. – georg 14 August 2018 в 12:23

Найдите функцию «sortFn» ниже. Эта функция сортируется по неограниченному числу параметров (например, в c #: SortBy (...). ThenBy (...). ThenByDesc (...)).

function sortFn() {
    var sortByProps = Array.prototype.slice.call(arguments),
        cmpFn = function(left, right, sortOrder) {
            var sortMultiplier = sortOrder === "asc" ? 1 : -1;

            if (left > right) {
                return +1 * sortMultiplier;
            }
            if (left < right) {
                return -1 * sortMultiplier;
            }
            return 0;
        };


    return function(sortLeft, sortRight) {
        // get value from object by complex key
        var getValueByStr = function(obj, path) {
            var i, len;

            //prepare keys
            path = path.replace('[', '.');
            path = path.replace(']', '');
            path = path.split('.');

            len = path.length;

            for (i = 0; i < len; i++) {
                if (!obj || typeof obj !== 'object') {
                    return obj;
                }
                obj = obj[path[i]];
            }

            return obj;
        };

        return sortByProps.map(function(property) {
            return cmpFn(getValueByStr(sortLeft, property.prop), getValueByStr(sortRight, property.prop), property.sortOrder);
        }).reduceRight(function(left, right) {
            return right || left;
        });
    };
}

var arr = [{
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 10000
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 2
        }
    }
}, {
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 100
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 1
        }
    }
}];
document.getElementsByTagName('pre')[0].innerText = JSON.stringify(arr)

arr.sort(sortFn({
    prop: "name",
    sortOrder: "asc"
}, {
    prop: "LocalizedData[en-US].Value",
    sortOrder: "desc"
}));

document.getElementsByTagName('pre')[1].innerText = JSON.stringify(arr)
pre {
    font-family: "Courier New" Courier monospace;
    white-space: pre-wrap;
}
Before:
<pre></pre>
Result:
<pre></pre>

0
ответ дан Igor Shubin 19 August 2018 в 04:07
поделиться

С ES6 вы можете сделать

array.sort(function(a, b) { 
 return SortFn(a.strength,b.strength) || SortFn(a.name,b.name)
})

 private sortFn(a, b): number {
    return a === b ? 0 : a < b ? -1 : 1;
}
0
ответ дан Josf 19 August 2018 в 04:07
поделиться

Вы можете связать порядок сортировки с логическим ИЛИ.

objects.sort(function (a, b) {
    return a.strength - b.strength || a.name.localeCompare(b.name);
});
15
ответ дан Nina Scholz 19 August 2018 в 04:07
поделиться
  • 1
    Это блестяще! Но как насчет случая, когда сила может быть неопределенной, и мы хотим, чтобы все объекты с определенной силой шли первым. Есть ли какое-то решение, столь же изящное, как это? – Nan Li 6 October 2016 в 23:59
  • 2
    может быть что-то вроде этого: return ((a.strength || Number.MAX_VALUE) - (b.strength || Number.MAX_VALUE)) || a.name.localeCompare (b.name); – Nan Li 7 October 2016 в 00:36
  • 3
    да, вы можете добавить значение по умолчанию для несуществующих частей, таких как return ((a.strength || Infinity) - (b.strength || Infinity)) || a.name.localeCompare(b.name);. но это зависит от возможного значения strength. – Nina Scholz 7 October 2016 в 06:01
  • 4
    работает как очарование return a.z - b.z || a.x - b.x || a.y - b.y – bresleveloper 1 November 2017 в 19:29
function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength) {return -1}
  else if (ob1.name > ob2.name) {return 1}
  return -1;
};

EDIT: Сортировка по силе, тогда, если сила равна, сортируйте по имени. Случай, когда сила и имя равны в обоих объектах, не нужно учитывать отдельно, так как окончательный возврат -1 указывает на отношения менее или равные. Результат сортировки будет правильным. Это может заставить его работать быстрее или медленнее, я не знаю. Если вы хотите быть явным, просто замените

return -1;

на

else if (ob1.name < ob2.name) {return -1}
return 0;
0
ответ дан steve 19 August 2018 в 04:07
поделиться
  • 1
    Вы пропустили равный случай. – T.J. Crowder 7 February 2012 в 13:24
  • 2
    Добавьте короткий текст, который немного объяснит ваш ответ ... – Daniele B 7 February 2012 в 13:38

Когда я искал ответ на этот вопрос, ответы, которые я нашел на StackOverflow, на самом деле не были тем, на что я надеялся. Поэтому я создал простую, многоразовую функцию, которая делает именно это. Он позволяет использовать стандартный массив Array.sort, но с использованием метода firstBy (). ThenBy (). ThenBy (). https://github.com/Teun/thenBy.js

PS. Это второй раз, когда я публикую это. Первый раз был снят модератором: «Пожалуйста, не делайте рекламные сообщения для своей собственной работы». Я не уверен, какие правила здесь, но я пытался ответить на этот вопрос. Мне очень жаль, что это моя собственная работа. Не стесняйтесь удалять снова, но, пожалуйста, укажите мне правило.

3
ответ дан Teun D 19 August 2018 в 04:07
поделиться
  • 1
    Вы должны поместить первое имя, последний пример в Readme.md, поскольку все после этого ^^, я дам эту попытку lib, выглядит хорошо. – Christophe Roussy 25 July 2017 в 11:50
  • 2
    Да, хороший момент, я думаю. Заманчиво демонстрировать действительно произвольные комбинации полей, но readme действительно должен начинаться с наиболее распространенного сценария. Спасибо за совет. – Teun D 28 August 2017 в 08:27
Другие вопросы по тегам:

Похожие вопросы: