Как визуализировать и элемент один раз в функции карты? У меня есть и массив объектов, и я хочу отобразить значение цвета только один раз в другой компонент, я попытался вставить цвет в массив и проверить его, но поскольку он находится внутри цикла, он добавляется мгновенно, и эта проверка потерпит неудачу, дело в том, что я не хочу, чтобы один и тот же цвет отображался дважды, если он найден, то только один раз… есть ли хорошее решение для этого случая?

const items =[{car : 'bmw', color : 'black'}, {car: 'opel', color :'black'}, {car:'landrover',color:'red'}]


 {items.map((item, i) => {
          let arr = [];
          //arr.push(items[i].color);
          return (
            <React.Fragment>
              {arr.includes(items[i]) ? undefined : <colors img={items[i]?.color} /> }
              <items key={item.id} Car={item.car} />
        </React.Fragment>
      );
    })}
    
    
    
    // Expected result 
    
    //  black color component
    // 'bmw'
    // 'opel'
    // red color component
    // 'landrover'
1
Richardson 4 Фев 2022 в 17:26
Похоже, ваша проблема связана с наличием повторяющегося элемента в массиве. Если да, то поможет ли этот ответ? stackoverflow.com/q/9229645/4592937
 – 
Connor Mooneyhan
4 Фев 2022 в 17:32

4 ответа

Лучший ответ

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

items
  .sort((a, b) => a.color.localeCompare(b.color))
  .map((item, index, sortedItems) => {
    const colorChanged = !index || item.color !== sortedItems[index - 1].color
    
    return (
      <>
        { colorChanged && <colors img={items[i]?.color} /> }
        <items key={item.id} Car={item.car} />
      </>
    )
  })

Редактировать: поскольку index является целым числом >= 0, !index будет оцениваться как true точно тогда, когда это делает index === 0.

2
Marces Engel 4 Фев 2022 в 17:40
Я не хочу возиться с сортировкой, но ваш ответ очень близок к тому, что я хочу, я собираюсь попробовать
 – 
Richardson
4 Фев 2022 в 17:50
1
Если вы можете быть уверены, что автомобили одного цвета всегда идут блоками (один за другим), вы можете пропустить часть сортировки :)
 – 
Marces Engel
4 Фев 2022 в 17:52
Они должны приходить блоками
 – 
Richardson
4 Фев 2022 в 18:00
const itemColors = items
  .map(({ color }) => color) // create array of colors
  .filter((value, index, self) => self.indexOf(value) === index) // remove duplicates

// do your rendering here

Или с помощью lodash

1
Matthew Kwong 4 Фев 2022 в 17:30
Мне все еще нужно отображать элементы в соответствии с этим массивом
 – 
Richardson
4 Фев 2022 в 17:34
Итак, вы только что изменили свой вопрос, и это немного меняет ситуацию. Вы не пытаетесь удалить дубликаты, вы пытаетесь сгруппировать массив по color. В этом случае вы либо пишете функцию groupBy самостоятельно, либо находите ее в служебной библиотеке, такой как lodash, которая имеет groupBy
 – 
Matthew Kwong
4 Фев 2022 в 17:37
    const items =[
     {car : 'bmw', color : 'black'}, 
     {car: 'opel', color :'black'}, 
     {car:'landrover',color:'red'}
    ]
    
    //Expected Outcome
    /*
      [
          {
            color: 'black'
            cars: ['bmw','opel']
          },
          {
            color: 'black'
            cars: ['bmw','opel']
          }
      ]
    */  

const finalResult = items.reduce((acc, cur, arr) => {
  let res = [...acc];
  const matchIndex = res.findIndex(obj => obj.color === cur.color);

  if (matchIndex === -1) {
    res.push({
      color: cur.color,
      cars: [cur.car]
    })
  } else {
    res[matchIndex].cars.push(cur.car)
  }

  acc = res;
  return acc;
}, []
)

console.log(finalResult);

finalResult.forEach(colorObject => {
  colorObject.cars.forEach(car => {
    console.log(
      `Your Component with Color ${colorObject.color} and Car ${car}`
    );
  })
})
1
M Shahzeb Raza 4 Фев 2022 в 18:15
Цикл довольно сложен, есть также элементы, которые нужно отобразить, представьте, если у объекта автомобиля есть другие элементы, такие как год, и я хочу отобразить цвет и годы под ним.
 – 
Richardson
4 Фев 2022 в 17:41

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

const colors = items
   .map((data) => data.color)
   .filter((v, i, s) => s.indexOf(v) === i) 

{colors.map((color) => (
    <div>
        {color}
        {items.filter(item => item.color === color).map((item)=> (
            <>{item.car}</>
        )}
    </div>
)}
0
Ahmmed Abir 4 Фев 2022 в 17:47