在不使用INCLUDES的情况下检查对象数组中是否存在值

时间:2018-11-06 21:57:51

标签: javascript html

标题说明:我真的不知道如何完美地命名这个问题。如果有人可以建议一个更合适的标题,请这样做。

我有一个表格,其中标题必须根据其名称的前7个字符进行着色。

前7个字符是 yyyy.mm 。例如2017.10。

这是我的需要:

  • 我希望每次出现的相同7个字符都具有相同的颜色(单元格的背景色)。换句话说,如果单元格的前7个字符为2017.10,则它们都应为同一颜色。如果是2017.09,则它们的颜色都应与2017.10或其他任何日期相同。

我正在尝试做,但是很难完成它。我觉得我接近了...

JS:

function setHeaderColor() {
  const mainTable = document.getElementById('main-table');
  const headerRow = document.querySelectorAll('#main-table tr:first-child th');
  const test = []; // Holds first 7 chars and background color of each column header
  const colors = [
    '#FF6633', '#FFB399', '#FF33FF', '#FFFF99', '#00B3E6',
    '#E6B333', '#3366E6', '#999966', '#99FF99', '#B34D4D',
    '#80B300', '#809900', '#E6B3B3', '#6680B3', '#66991A',
    '#FF99E6', '#CCFF1A', '#FF1A66', '#E6331A', '#33FFCC',
    '#66994D', '#B366CC', '#4D8000', '#B33300', '#CC80CC',
    '#66664D', '#991AFF', '#E666FF', '#4DB3FF', '#1AB399',
    '#E666B3', '#33991A', '#CC9999', '#B3B31A', '#00E680',
    '#4D8066', '#809980', '#E6FF80', '#1AFF33', '#999933',
    '#FF3380', '#CCCC00', '#66E64D', '#4D80CC', '#9900B3',
    '#E64D66', '#4DB380', '#FF4D4D', '#99E6E6', '#6666FF'
  ];

  headerRow[1].style.backgroundColor = colors[1];

  // Extract first 7 characters from column header name
  for (let i = 0; i < headerRow.length; i++) {
    test.push({
      version: headerRow[i].innerHTML.substring(0, 7),
      color: headerRow[i].style.backgroundColor || null
    });
  }

  for (let i = 1; i < test.length; i++) {
    if (test[i].version === test[i - 1].version) {
      test[i].color = test[i - 1].color
    } else {
      test[i].color = colors[Math.floor(Math.random() * colors.length)];
    }
  }

  for (let i = 0; i < headerRow.length; i++) {
    headerRow[i].style.backgroundColor = test[i].color;
  }
}

document.addEventListener('DOMContentLoaded', setHeaderColor);
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

<table class="w3-table-all" id="main-table">
  <tr>
    <th class="w3-center"> Name</th>
    <th class="w3-center">2017.10-T-2018_08_30 ms_201709.</th>
    <th class="w3-center">2017.09-T-2018_08_30 ms_201709.</th>
    <th class="w3-center">2017.10-T-2018_08_30 ms_201709</th>
    <th class="w3-center">2017.09-T-2018_08_30 ms_201709</th>
    <th class="w3-center">2017.08-T-2018_08_30 ms_201709</th>
  </tr>
</table>

如您所见,每次颜色都是不同的。我现在正在做的是将单元格与上一个单元格([i - 1])进行比较。我知道我应该检查数组test中是否存在该值,然后获取其关联的颜色,但是我无法提出一种实现方法。我尝试了indexOfincludes,但没有成功...

3 个答案:

答案 0 :(得分:1)

因此只需创建一个查找表,如果该键存在,则返回它,如果它没有获取新的颜色。

const colors = ['#FF6633', '#FFB399', '#FF33FF', '#FFFF99', '#00B3E6']
const used = {}
function getColor (key) {
  used[key] = used[key] || colors.shift()
  return used[key]
}

console.log("aaa", getColor("aaa"))
console.log("bbb", getColor("bbb"))
console.log("aaa", getColor("aaa"))
console.log("bbb", getColor("bbb"))

如何存储,请使用localStorage

// default color list
const colors = ['#FF6633', '#FFB399', '#FF33FF', '#FFFF99', '#00B3E6']
// read local storage, if empty, than use empty object
const used = JSON.parse(localStorage.getItem("used") || "{}")
// remove any colors used already so we do not reuse them
Object.values(used).forEach(cc => {
  // find it in the array
  const ind = colors.indexOf(cc)
  // if found, remove it
  if (ind > -1 ) {
    colors.splice(ind, 1)
  }
})

function getColor (key) {
  // check if we have it, if not grab a new one
  used[key] = used[key] || colors.shift()
  // return the code
  return used[key]
}

console.log("aaa", getColor("aaa"))
console.log("bbb", getColor("bbb"))
console.log("aaa", getColor("aaa"))
console.log("bbb", getColor("bbb"))
console.log("bbb", getColor("ccc"))

// set the localstorage with the used values
localStorage.setItem("used", JSON.stringify(used))

答案 1 :(得分:0)

听起来好像您想查找是否以前已将颜色值分配给yyyy.mm字符串。这种查找的最佳数据结构是映射,而不是数组。

在Javascript中,将对象用作哈希映射是很常见的:

const colorMap = {};
const colors = ['#FF6633', '#FFB399', '#FF33FF']

// use this function by passing in your "yyyy.mm" strings 
function getColorFor(firstSevenChars) {
    if(colorMap[firstSevenChars] !== undefined) {
         // we've encountered this character combo before! 
         // retrieve the corresponding color.
         return colorMap[firstSevenChars];
    }
   
    // get the next free color, which is the n+1th color, 
    // n being the number of colours already assigned.
    // use modulo (%) to ensure that we don't exceed the colors array.
    let newColor = colors[ Object.keys(colorMap).length % colors.length ];
     
    // associate the yyyy.mm code with the new color and return it.
    colorMap[firstSevenChars] = newColor;
    return newColor;
}

console.log("2018.01", getColorFor("2018.01"));
console.log("2018.02", getColorFor("2018.02"));
console.log("2018.03", getColorFor("2018.03"));
console.log("out of colors! loop through them again...");
console.log("2018.04", getColorFor("2018.04"));
console.log("2018.05", getColorFor("2018.05"));

答案 2 :(得分:0)

您需要使用一个内部for循环,它将查找所有匹配的版本并设置颜色。

将循环更改为以下内容。

for (let i = 1; i < test.length; i++) {
    for(let j=i;j<test.length; j++){
        if (test[i].version === test[j].version) {
          test[i].color = test[j].color
        } else {
          test[i].color = colors[Math.floor(Math.random() * colors.length)];
        }
    }
}