根据版本号排序表

鲈鱼

我想根据版本号对表格进行排序,最高在顶部。如果单元格以“v”开头,后跟一个数字,则它被视为版本号。否则,它应该按字母顺序排列在表格的底部。

结果目前正是我想要的方式,除了 v2.0 应该在 v2a 之前,v2a 应该在 v2b 之前。我知道我parseFloat()正在搞砸,但我怎样才能以更好的方式做到这一点?

function sortTable(table, order, selector, target) {
	selector = selector || 'th:first-child, td:first-child';
	var asc = order === 'asc';
	target = target || '';
	
	var tbody = table.querySelector('tbody') || table;
	var nodes = tbody.querySelectorAll('tr');
	var sortedNodes = Array.prototype.slice.apply(nodes);
	sortedNodes.sort(function (a, b) {
		var textA = a.querySelector(selector).textContent;
		var textB = b.querySelector(selector).textContent;
		if( target == 'versions' )
		{
			if (textA.match(/^v\d.*/i)) {
				textA = parseFloat(textA.substr(1));
			}
			if (textB.match(/^v\d.*/i)) {
				textB = parseFloat(textB.substr(1));
			}
		
		}
		result = textA - textB;
		if (isNaN(result))
		{
			return (asc && textB.toString() != '' ) ? textA.toString().localeCompare(textB) : textB.toString().localeCompare(textA);
		}
		else
		{
			return (asc) ? -result : result;
		}
	});
	tbody.textContent = '';
	for (var i = 0; i < sortedNodes.length; i++) {
		tbody.appendChild(sortedNodes[i]);
	}
}
sortTable(document.getElementById('versions'), 'asc', '', 'versions');
<table id="versions">
	<tbody>
		<tr><td>Text</td></tr>
		<tr><td>v2b</td></tr>
		<tr><td>v3.0</td></tr>
		<tr><td>v2a</td></tr>
		<tr><td></td></tr>
		<tr><td>v2.0</td></tr>
		<tr><td>No version number</td></tr>
		<tr><td>v1.0 Work in Progress</td></tr>
	</tbody>
</table>

雷哈特菲尔德

您可以使用 RegEx 拆分版本号和后缀,以确保正确处理数字部分。

我不是 100% 确定这个片段涵盖了所写的所有可能的情况它处理您的样本数据,并且可以轻松调整以处理存在的边缘情况。

为了排序的清晰性和简单性,我省略了 DOM 内容。 除了原始文本值之外,我还更新了代码片段以演示基本的表格排序。

const values = [
  "Text",
  "v2b",
  "v3.0",
  "v2a",
  "",
  "v2.0",
  "v30.4alpha",
  "No version number",
  "v1.0 Work in Progress",
];

// regex to separate the numeric version from the suffix
// e.g. "v2.0a" => ["2.0", "a"]
const version = /v(\d+(?:\.\d+)*)(.*)/;

function getSortValue (item) {
  if (item == null ) {
    return item;
  }
  
  // might want to do something more robust here.
  // if it's not a string this assumes it's a tr
  // and the first cell has the text we care about.
  return typeof item === "string"
    ? item
    : item.firstChild.textContent;
}

function sort(av, bv) {
  const a = getSortValue(av);
  const b = getSortValue(bv);
  
  if (b && !a) {
    return 1;
  }

  if (a && !b) {
    return -1;
  }
  // get the numeric version and suffix for each item,
  // OR'd with [] for cases where the regex doesn't match
  const [, aVersion = 0, aSuffix = ''] = version.exec(a) || [];
  const [, bVersion = 0, bSuffix = ''] = version.exec(b) || [];

  // sort on the numeric portion
  const versionDiff = parseFloat(bVersion) - parseFloat(aVersion);

  // if the numeric versions are the same
  // sort on the suffix
  if (versionDiff === 0) {
    return aSuffix.localeCompare(bSuffix) || a.localeCompare(b);
  }

  // numeric versions are different; sorting them is enough.
  return versionDiff;
}

// sort raw text values
document.querySelector('pre').innerHTML = JSON.stringify(values.sort(sort), null, 2);

// sort table rows
const rows = Array.from(document.querySelectorAll('tr'));
rows.sort(sort);
const tbody = rows[0].parentElement;
rows.forEach(r => tbody.append(r));
table {
  width: 100%;
  font-family: monospace;
  font-size: 14px;
}

td {
  padding: 4px 8px;
}

tr:nth-child(2n - 1) {
  background: #eee;
}
<table id="versions">
	<tbody>
		<tr><td>Text</td></tr>
		<tr><td>v2b</td></tr>
		<tr><td>v3.0</td></tr>
		<tr><td>v2a</td></tr>
		<tr><td></td></tr>
		<tr><td>v2.0</td></tr>
		<tr><td>No version number</td></tr>
		<tr><td>v1.0 Work in Progress</td></tr>
	</tbody>
</table>

<pre></pre>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章