Преобразование массива в Javascript [дубликат]

Вы можете заставить его работать со следующим Binding:

Binding="{Binding Path=.}

Но он не решит вашу проблему, потому что строки являются типичными, которые являются неизменяемыми, то есть вы не можете изменить ссылку на строку, с которой вы привязались ваш пользовательский интерфейс.

Итак, ваши мысли верны, вам нужно будет обернуть эти строки в объекты, использовать свойство path для привязки и передать эти объекты в ваш DataGrid.

public class StringWrapper
{
    public string Value { get; set; }
}
36
задан 1983 29 July 2015 в 01:36
поделиться

10 ответов

Во-первых, в JavaScript обычно не рекомендуется перебирать массивы с помощью for ... in. См. Почему используется & quot; для ... в & quot;

Итак, вы можете попробовать что-то вроде этого:

var groups = {};
for (var i = 0; i < myArray.length; i++) {
  var groupName = myArray[i].group;
  if (!groups[groupName]) {
    groups[groupName] = [];
  }
  groups[groupName].push(myArray[i].color);
}
myArray = [];
for (var groupName in groups) {
  myArray.push({group: groupName, color: groups[groupName]});
}

Использование промежуточного объекта groups здесь помогает ускорить работу потому что он позволяет избежать циклов вложенности для поиска по массивам. Кроме того, поскольку groups является объектом (а не массивом), итерация по нему с использованием for ... in является подходящей.

Добавление

FWIW, если вы хотите избежать дублирования записей цвета в результирующих массивах вы можете добавить оператор if над строкой groups[groupName].push(myArray[i].color);, чтобы защитить от дубликатов. Используя jQuery, он будет выглядеть следующим образом:

if (!$.inArray(myArray[i].color, groups[groupName])) {
  groups[groupName].push(myArray[i].color);
}

Без jQuery вы можете добавить функцию, которая выполняет ту же функцию, что и jQuery inArray:

Array.prototype.contains = function(value) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] === value)
      return true;
  }
  return false;
}

, а затем используйте это следующим образом:

if (!groups[groupName].contains(myArray[i].color)) {
  groups[groupName].push(myArray[i].color);
}

Обратите внимание, что в любом случае вы собираетесь немного замедлить работу из-за всей дополнительной итерации, поэтому, если вам не нужно избегать дублирования записей цвета в Я бы рекомендовал избегать этого дополнительного кода. Там

22
ответ дан Community 15 August 2018 в 17:04
поделиться
  • 1
    Извините, но это не сработает, если у вас есть два одинаковых объекта в _myArray_. With var myArray = [ {group: "one", color: "red"}, {group: "two", color: "blue"}, {group: "one", color: "green"}, {group: "one", color: "black"}, {group: "one", color: "black"} ];. Вы получите myArray[0].color = ["red", "green", "black", "black"] – Lends 28 July 2015 в 23:32
  • 2
    & quot; Не работает & quot; является субъективным. OP никогда не заявлял, что делать в этом случае. – Jan 28 July 2015 в 23:34
  • 3
    @ Заставляет OP никогда не указывать это как требование. На самом деле, учитывая комментарий от ОП, я бы сказал, что это решение действительно «работает». – neuronaut 28 July 2015 в 23:41
  • 4
    @neuronaut извините, но, возможно, автор просто не проверял его, и нет никаких требований, кроме формата объектов в массиве. Неважно, ваш ответ подтвержден, и я не пытаюсь судить вас. Но было бы здорово, если бы у вас было время исправить эту ошибку, чтобы другие люди могли использовать ваш код вместо дублирования этой темы. Благодаря! – Lends 28 July 2015 в 23:46
  • 5
    Выложенное решение удовлетворяет требованиям, в этом вопросе ничего не говорится о том, как обрабатывать дубликаты. A "fix" для неопределенной проблемы, вероятно, будет более запутанным для будущих читателей, которые не ожидают такой функциональности. – Jan 28 July 2015 в 23:48

Начните с создания сопоставления имен групп со значениями. Затем преобразование в желаемый формат.

var myArray = [
    {group: "one", color: "red"},
    {group: "two", color: "blue"},
    {group: "one", color: "green"},
    {group: "one", color: "black"}
];

var group_to_values = myArray.reduce(function (obj, item) {
    obj[item.group] = obj[item.group] || [];
    obj[item.group].push(item.color);
    return obj;
}, {});

var groups = Object.keys(group_to_values).map(function (key) {
    return {group: key, color: group_to_values[key]};
});

var pre = document.createElement("pre");
pre.innerHTML = "groups:\n\n" + JSON.stringify(groups, null, 4);
document.body.appendChild(pre);

Использование методов экземпляра Array, таких как , уменьшает и карту дает вам мощные конструкции более высокого уровня, которые могут сэкономить вам много боли в ручном режиме.

52
ответ дан 1983 15 August 2018 в 17:04
поделиться
  • 1
    Работает, как прелесть, спасибо. – Human Askari 12 April 2017 в 10:26
  • 2
    Отличный ответ. С Object.entries и ES6 мы также можем сделать groups = Object.entries(group_to_values).map(([group, color]) => ({ group, color })); – a15n 12 July 2017 в 22:39
  • 3
    Потрясающие! моя проблема заключалась в том, чтобы вытаскивать ключи для создания массива объектов с помощью Object.keys – William 2 August 2017 в 15:20
  • 4
    как бы я сделал, чтобы получить еще один элемент в конечном объекте, если мой исходный массив выглядит как {group: & quot; one & quot ;, color: & quot; red & quot ;, size: & quot; big & quot;}? – Jonathan 11 August 2017 в 09:27
  • 5
    Отлично! Большое спасибо. – Huy Nguyen 26 June 2018 в 11:07

Используя методы Array reduce и findIndex, это может быть достигнуто.

var myArray = [{
  group: "one",
  color: "red"
}, {
  group: "two",
  color: "blue"
}, {
  group: "one",
  color: "green"
}, {
  group: "one",
  color: "black"
}];

var transformedArray = myArray.reduce((acc, arr) => {
  var index = acc.findIndex(function(element) {
    return element.group === arr.group;
  });
  if (index === -1) {
    return acc.push({
      group: arr.group,
      color: [arr.color]
    });
  }
  
  acc[index].color.push(arr.color);
  return acc;
}, []);

console.log(transformedArray);

Используя функцию reduce, массив является итератором, а новые значения сохраняются в параметре acc (accumulating). Чтобы проверить, существует ли объект с заданным group, мы можем использовать функцию findIndex.

Если findIndex() возвращает -1, значение не существует, поэтому добавьте массив в acc параметр.

Если findIndex() возвращает индекс, то обновите index с помощью значений arr.

0
ответ дан Anurag Singh Bisht 15 August 2018 в 17:04
поделиться

Эта версия использует преимущества того, что ключи объектов уникальны. Мы обрабатываем исходный массив и собираем цвета по группе в новом объекте. Затем создайте новые объекты из этой группы -> массив массивов цветов.

var myArray = [{
      group: "one",
      color: "red"
    }, {
      group: "two",
      color: "blue"
    }, {
      group: "one",
      color: "green"
    }, {
      group: "one",
      color: "black"
    }];

    //new object with keys as group and
    //color array as value
    var newArray = {};

    //iterate through each element of array
    myArray.forEach(function(val) {
      var curr = newArray[val.group]

      //if array key doesnt exist, init with empty array
      if (!curr) {
        newArray[val.group] = [];
      }

      //append color to this key
      newArray[val.group].push(val.color);
    });

    //remove elements from previous array
    myArray.length = 0;

    //replace elements with new objects made of
    //key value pairs from our created object
    for (var key in newArray) {
      myArray.push({
        'group': key,
        'color': newArray[key]
      });
    }

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

2
ответ дан Brandon 15 August 2018 в 17:04
поделиться

Использовать метод lodash groupby

Создает объект, состоящий из ключей, сгенерированных из результатов запуска каждого элемента коллекции через iteratee. Порядок группируемых значений определяется порядком их возникновения в коллекции. Соответствующее значение каждой клавиши представляет собой массив элементов, ответственных за генерацию ключа. Итератор вызывается одним аргументом: (значение).

Таким образом, с помощью lodash вы можете получить то, что хотите в одной строке. См. Ниже

let myArray = [
  {group: "one", color: "red"},
  {group: "two", color: "blue"},
  {group: "one", color: "green"},
  {group: "one", color: "black"},
]
let grouppedArray=_.groupBy(myArray,'group')
console.log(grouppedArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

5
ответ дан husayt 15 August 2018 в 17:04
поделиться
  • 1
    результат не является необходимой структурой данных – Ibrahim Mohammed 4 August 2018 в 22:08

Помимо данных подходов с двухпроходным подходом, вы можете выбрать один цикл, нажав группу, если будет найдена новая группа.

var array = [{ group: "one", color: "red" }, { group: "two", color: "blue" }, { group: "one", color: "green" }, { group: "one", color: "black" }],
    groups = Object.create(null),
    grouped = [];

array.forEach(function (o) {
    if (!groups[o.group]) {
        groups[o.group] = [];
        grouped.push({ group: o.group, color: groups[o.group] });
    }
    groups[o.group].push(o.color);
});

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

2
ответ дан Nina Scholz 15 August 2018 в 17:04
поделиться

Вы можете сделать что-то вроде этого:

function convert(items) {
    var result = [];

    items.forEach(function (element) {
        var existingElement = result.filter(function (item) {
            return item.group === element.group;
        })[0];

        if (existingElement) {
            existingElement.color.push(element.color);
        } else {
            element.color = [element.color];
            result.push(element);
        }

    });

    return result;
}
0
ответ дан Papzord 15 August 2018 в 17:04
поделиться
var array = [{
      id: "123",
      name: "aaaaaaaa"
    }, {
      id: "123",
      name: "aaaaaaaa"
    }, {
      id: '456',
      name: 'bbbbbbbbbb'
    }, {
      id: '789',
      name: 'ccccccccc'
    }, {
      id: '789',
      name: 'ccccccccc'
    }, {
      id: '098',
      name: 'dddddddddddd'
    }];
//if you want to group this array
group(array, key) {
  console.log(array);
  let finalArray = [];
  array.forEach(function(element) {
    var newArray = [];
    array.forEach(function(element1) {
      if (element[key] == element1[key]) {
          newArray.push(element)
      }
    });
    if (!(finalArray.some(arrVal => newArray[0][key] == arrVal[0][key]))) {
        finalArray.push(newArray);
    }
  });
  return finalArray
}
//and call this function
groupArray(arr, key) {
  console.log(this.group(arr, key))
}
1
ответ дан sidhuko 15 August 2018 в 17:04
поделиться

Один из вариантов:

var res = myArray.reduce(function(groups, currentValue) {
    if ( groups.indexOf(currentValue.group) === -1 ) {
      groups.push(currentValue.group);
    }
    return groups;
}, []).map(function(group) {
    return {
        group: group,
        color: myArray.filter(function(_el) {
          return _el.group === group;
        }).map(function(_el) { return _el.color; })
    }
});

http://jsfiddle.net/dvgwodxq/

5
ответ дан undefined 15 August 2018 в 17:04
поделиться
  • 1
    Очень элегантный и самодостаточный, приятный. Моя единственная проблема заключается в том, что она не так легко читается, как более простой цикл for. – Jan 28 July 2015 в 23:46
  • 2
    уменьшить, indexOf, карта, фильтр, карта кажется слишком сложной для меня. – 1983 29 July 2015 в 01:00
  • 3
    @KingMob Определить «сложный». Это обычные методы массива. – undefined 29 July 2015 в 03:18
  • 4
    Это работает, но мне нужно время, чтобы пройти через код и понять его. Большое спасибо за вашу помощь! – Nuno Nogueira 29 July 2015 в 07:59
  • 5
    @NunoNogueira Приветствую вас. Это только один из вариантов. – undefined 29 July 2015 в 10:38
1
ответ дан Eddie 29 October 2018 в 00:05
поделиться
Другие вопросы по тегам:

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