Алгоритм JavaScript для сортировки массива в объекте по нескольким критериям - PullRequest
1 голос
/ 05 мая 2019

Я пытаюсь написать алгоритм, который сортирует эту таблицу по среднему значению из каждого столбца, сгруппированного по первому столбцу (имени), чтобы в таблице отображались только строки с наиболее распространенными значениями. Например, это текущий таблица:

unsorted table

и после сортировки должно выглядеть так:

sorted table

Итак, это массив, который я пытаюсь отсортировать и показать только самые распространенные табличные значения:

            var testArray = [
            {
                "testName": "10b1",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": "NORM",
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": "NEG"

            },
            {
                "testName": "10b1",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": "NORM",
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": "NEG"
            },
            {
                "testName": "10b1",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": "NORM",
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": "NEG"
            },
            {
                "testName": "10b1",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": "NORM",
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": "NEG"
            },
            {
                "testName": "10b1",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": "NORM",
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": "NEG"
            },
            {
                "testName": "10b1.5",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": 50,
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": 50
            },
            {

                "testName": "10b1.5",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": 50,
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": 50
            },
            {
                "testName": "10b1.5",
                "SG": 1.010,
                "pH":6,
                "LEU": "NEG",
                "NIT": "NEG",
                "PRO": "NEG",
                "GLU": 50,
                "KET": "NEG",
                "UBG": "NORM",
                "BIL": "NEG",
                "Hb": 50
            }
        ];

Я пытался использовать этот алгоритм, но результат, который возвращает меня, далек от ожидаемого результата:

  var mf = 1;
        var m = 0;
        var item;
        var count = 1;
        for(let k = 0; k < testArray.length; k++){
            for(let v = 0; v < testArray[k].values.length; v++){
                 current = 1;
                for(j = v; j <= testArray[k].values.length; j++){
                    if(testArray[k].values[v] == testArray[k].values[j]){
                        m++;
                    }

                    if(mf < m){
                        mf=m;
                        item = testArray[k].values[v];
                        testArray[k].values = [];
                    }
                }
                    testArray[k].values[v] = item;

            }

        }

Буду признателен, если кто-нибудь даст пример алгоритма или решение проблемы:)

1 Ответ

0 голосов
/ 06 мая 2019

Вы можете пройтись по массиву и создать вложенный объект для группировки массива на основе имени, затем по ключу и, наконец, по значению для каждого ключа. Затем выполните цикл entries этого counts вложенного объекта и создайте объект на основе режима значений для каждого ключ

Вот как выглядит counts объект:

{
    "10b1": {
        "SG": {
            "1.01": 5
        },
        "pH": {
            "6": 5
        },
        "LEU": {
            "NEG": 5
        },
        "NIT": {
            "NEG": 5
        },
        "PRO": {
            "NEG": 5
        },
        "GLU": {
            "NORM": 5
        },
        "KET": {
            "NEG": 5
        },
        "UBG": {
            "NORM": 5
        },
        "BIL": {
            "NEG": 5
        },
        "Hb": {
            "10": 3,
            "NEG": 2
        }
    },
    "10b1.5": {
        "SG": {
            "1.01": 3
        },
        "pH": {
            "6": 3
        },
        "LEU": {
            "NEG": 3
        },
        "NIT": {
            "NEG": 3
        },
        "PRO": {
            "NEG": 3
        },
        "GLU": {
            "50": 3
        },
        "KET": {
            "NEG": 3
        },
        "UBG": {
            "NORM": 3
        },
        "BIL": {
            "NEG": 3
        },
        "Hb": {
            "50": 3
        }
    }
}

Вот рабочий фрагмент:

{ testName, ...rest } в параметре reduce предназначен для деструктурирования каждого объекта в отдельный testName и оставшихся свойств объекта rest

var array=[{testName:"10b1",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:"NORM",KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:"NEG"},{testName:"10b1",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:"NORM",KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:"10"},{testName:"10b1",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:"NORM",KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:"NEG"},{testName:"10b1",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:"NORM",KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:"10"},{testName:"10b1",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:"NORM",KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:"10"},{testName:"10b1.5",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:50,KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:50},{testName:"10b1.5",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:50,KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:50},{testName:"10b1.5",SG:1.01,pH:6,LEU:"NEG",NIT:"NEG",PRO:"NEG",GLU:50,KET:"NEG",UBG:"NORM",BIL:"NEG",Hb:50}];

const counts = array.reduce((acc, { testName, ...rest }) => {
   if(!acc[testName]) acc[testName] = {};

   let nested = acc[testName];
   
   Object.entries(rest).forEach(([key, value]) => {
    if(!nested[key]) nested[key] = {}
    
    nested[key][value] = nested[key][value] + 1 || 1;
  })
  
  return acc
},{})

const output = Object.entries(counts).map(([testName, count]) => {
  const obj = { testName };
  
  Object.entries(count).forEach(([k, v]) => {
    const mode = Object.keys(v).sort((a, b) => v[b] - v[a])[0];
    obj[k] = mode;
  }, {})
  
  return obj
})

console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }

(Ни у одного из ключей не было более одного уникального value. Итак, для свойства 10b1 name's Hb я использовал: "NEG", "10", "NEG", "10", "10" значения - такие же, как изображение для демонстрации)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...