Решения
То, что вы хотите сделать, сводится к фильтрации неуникальных элементов из списка. Если я правильно понимаю, что вы хотите сохранить неповрежденными столбцы C
и D
, вам просто нужно сделать логику c более понятной, введя вспомогательную функцию (кстати, includes
требует переключения на среду выполнения V8 , если это не новый проект) и setValues
для того же rng
(см. Улучшение ниже 3)
/**
* Removes duplicates
* @param {any[]} array 2D input
* @returns {any[]} filtered input
*/
const filterDuplicates = (array) => {
const stack = [];
return array.filter(elem => {
const joined = elem.join('');
if( stack.includes(joined) ) {
return false;
}
stack.push(joined);
return true;
});
};
const [ input, output, tbody, tbody_init ] = document.querySelectorAll('#input, #output, #grid_init, #grid');
const buildCellGrid = (parent, grid) => {
parent.innerHTML = '';
for(const row of grid) {
const tr = document.createElement('tr');
for(const cell of row) {
const td = document.createElement('td');
td.textContent = cell;
tr.append(td);
}
parent.append(tr);
}
};
input.addEventListener('change',event=> {
const { value } = event.target;
const parsedVal = JSON.parse(value);
const filtered = filterDuplicates(parsedVal);
output.textContent = JSON.stringify(filtered, null, '');
buildCellGrid(tbody_init, filtered);
buildCellGrid(tbody, parsedVal);
});
p, textarea {
margin: 0 2vw;
}
textarea {
padding: 2vh 2vw;
line-height: 2;
resize: none;
width: 125px;
height: 125px;
}
table {
margin: 2vh 2vw;
border-collapse: collapse;
}
th, td {
padding: 1vh;
border: 1px solid darkgrey;
}
<p>
Enter valid 2D Array
</p>
<textarea id="input"></textarea>
<textarea id="output"></textarea>
<table>
<caption>Initial</caption>
<tbody id="grid_init"></tbody>
</table>
<table>
<caption>Filtered</caption>
<tbody id="grid"></tbody>
</table>
Улучшения
- Вы можете отказаться от вызова
Array
конструктора (new Array()
) к более распространенным и менее многословным буквальным обозначениям []
. Единственная интересная особенность - это выделение пустого Array
длины N с new Array(N)
(я иногда использую его с fill(whatever_value)
). - Не используйте
for...in
для массивов - это утверждение имеет его собственное использование (с Object
с). Пожалуйста, используйте for...of
, который предназначен для работы. - Вам не нужно
getRange()
new Range
для обновленных значений, так как они по определению являются подсеткой исходных значений, и вы предварительно очищаете диапазон с clearContents()
[Я полагаю Вы имели в виду clearContent()
].
Примечания
- Если вы заинтересованы Вот полуинтерактивное сравнение подходов к созданию нового экземпляра
Array
:
const li = (parent) => (txt) => {
const elem = document.createElement('li');
elem.textContent = txt || 'undefined';
parent.append(elem);
}
const forAll = (...args) => (callback) => {
for(const arg of args) {
callback(arg);
}
};
const genConstrArr = (numElems) => {
const temp = [];
let i = 0;
while(i < numElems) {
temp.push(`${i++} elem`);
}
return new Array(...temp);
};
const genArr = (numElems) => {
const arr = [];
let i = 0;
while(i < numElems) {
arr.push(`${i++} elem`);
}
return arr;
};
const buildList = (container, array) => {
const lists = container.querySelectorAll('ul');
const [inList, ofList, keysList, ownList, symList] = lists;
forAll(...lists)(list => list.innerHTML = '');
for(const key in array) {
li(inList)(key);
}
forAll(...array)( li(ofList) );
const emptyKeys = Object.keys(array);
forAll(...emptyKeys)( li(keysList) );
const names = Object.getOwnPropertyNames(array);
forAll(...names)( li(ownList) );
const symbols = Object.getOwnPropertySymbols(array);
forAll(...symbols)( li(symList) );
forAll(...lists)(list => !list.hasChildNodes() && li(list)('[Empty]'));
};
const boxes = document.querySelectorAll('#constructor, #constructor_filled, #literal');
const form = document.forms.array_control;
form.addEventListener('change', event => {
const { value } = event.target;
buildList(boxes[0], new Array(+value));
buildList(boxes[1], genConstrArr(+value));
buildList(boxes[2], genArr(+value));
});
input {
margin: 4vh 0;
}
ul {
list-style: none;
padding: 0;
}
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 2vh 2vw;
}
td {
vertical-align: baseline;
}
<form id="array_control">
<label for="elems">Number of elements:</label>
<input id="elems" min="0" name="elems" type="number" />
</form>
<table>
<thead>
<tr>
<th></th>
<th>for...in</th>
<th>for...of</th>
<th>Object.keys()</th>
<th>getOwnPropertyNames()</th>
<th>getOwnPropertySymbols()</th>
</tr>
</thead>
<tbody>
<tr id="constructor">
<th>Constructor (1 arg)</th>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
</tr>
<tr id="constructor_filled">
<th>Constructor (>1 arg)</th>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
</tr>
<tr id="literal">
<th>Literal</th>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
<td><ul></ul></td>
</tr>
</tbody>
</table>
Ссылки
- JS Лексическая грамматика на MDN
- Перечислимость и собственность свойств
Set
встроенных документов в MDN for...in
документы и for...of
документы на MDN