根据字符串中的前两个数字重新排列行
Reorder lines in a string based on first two numbers inside
我从一个不相关的源获得一些字符串data
,其中包含(除其他文本外)遵循类似于^INSERT INTO 'w VALUES ('d, .*$
模式的行。我想做的是根据第一列(如果第二列是数字,那么第二列也是)的值对这些行进行排序。
到目前为止,对于第一个值有严格增量的行,我所掌握的代码运行良好,但当值重复时,逻辑中断,而是输出undefined
。我还想知道,如果第一个数字重复,我如何根据第二个数字进行排序。
按多个属性排序本身对我来说不是问题,问题是我的对象设置方式(因为每个ID使用一个对象键,所以它们不允许重复ID)。
var data =
"--'n'
-- PostgreSQL database dump'n'
--'n'
'n'
SET statement_timeout = 0;'n'
SET lock_timeout = 0;'n'
SET client_encoding = 'UTF8';'n'
SET standard_conforming_strings = on;'n'
SET check_function_bodies = false;'n'
SET client_min_messages = warning;'n'
'n'
-- Working fine'n'
INSERT INTO c VALUES (3, 'c', 45);'n'
INSERT INTO c VALUES (1, 'a', 11);'n'
INSERT INTO c VALUES (5, 'e', 77);'n'
INSERT INTO c VALUES (4, 'd', 76);'n'
INSERT INTO c VALUES (2, 'b', 33);'n'
'n'
--'n'
-- Name: a; Type: TABLE; Schema: public'n'
--'n'
CREATE TABLE a ('n'
first integer NOT NULL,'n'
second integer NOT NULL'n'
);'n'
'n'
--'n'
-- Name: a_first_second; Type: CONSTRAINT; Schema: public'n'
--'n'
ALTER TABLE ONLY a'n'
ADD CONSTRAINT a_first_second PRIMARY KEY (first, second);'n'
'n'
-- Breaks'n'
INSERT INTO a VALUES (1, 1);'n'
INSERT INTO a VALUES (2, 5);'n'
INSERT INTO a VALUES (4, 2);'n'
INSERT INTO a VALUES (5, 6);'n'
INSERT INTO a VALUES (2, 4);'n'
INSERT INTO a VALUES (3, 7);'n'
INSERT INTO a VALUES (4, 6);'n'
INSERT INTO a VALUES (2, 7);'n'
INSERT INTO a VALUES (6, 9);'n'
'n'
-- All good here'n'
INSERT INTO b VALUES (2, 'b', 'Description');'n'
INSERT INTO b VALUES (3, 'c', 'Description'n'
2nd line of description');'n'
INSERT INTO b VALUES (1, 'a', 'Description');'n'
INSERT INTO b VALUES (4, 'd', 'Description'n'
2nd line of description'n'
3rd line of description');'n'
INSERT INTO b VALUES (5, 'e', 'Description');";
/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/document.body.innerHTML='<code><pre></pre></code>';console = {log:function(input){document.getElementsByTagName('pre')[0].innerHTML+=input+''n'}};
var groups = {},
test = /INSERT INTO "?([a-z]+)"?'s*VALUES's*'(('d+),['s'S]+?;/g;
data.replace(test,function(row,group,field){
if (typeof groups[group] !== 'object')
groups[group] = {};
groups[group][field] = row;
return row;
});
var sortedGroupKeys = {},
groupStep = {};
for (var j = 0, k = Object.keys(groups), l = k.length; j<l; j++){
var group = k[j];
sortedGroupKeys[group] = Object.keys(groups[group]).sort(function(a,b){
return parseInt(a, 10) - parseInt(b, 10);
});
groupStep[group] = 0;
}
data = data.replace(test,function(row,group){
var nextSortedKeyIndex = groupStep[group]++,
nextSortedKey = sortedGroupKeys[group][nextSortedKeyIndex];
return groups[group][nextSortedKey];
});
console.log(data);
这里的基本轮廓是:
- 拆分并迭代表插入块
- 拆分为"插入命令行"
- 对行进行排序
- 加入行
- 连接块
var data =
"-- Working fine'n'
INSERT INTO c VALUES (3, 'c', 45);'n'
INSERT INTO c VALUES (1, 'a', 11);'n'
INSERT INTO c VALUES (5, 'e', 77);'n'
INSERT INTO c VALUES (4, 'd', 76);'n'
INSERT INTO c VALUES (2, 'b', 33);'n'
'n'
-- Breaks (but not really broken anymore)'n'
INSERT INTO a VALUES (1, 1);'n'
INSERT INTO a VALUES (2, 5);'n'
INSERT INTO a VALUES (6, 11);'n'
INSERT INTO a VALUES (6, 20);'n'
INSERT INTO a VALUES (4, 2);'n'
INSERT INTO a VALUES (5, 6);'n'
INSERT INTO a VALUES (2, 4);'n'
INSERT INTO a VALUES (3, 7);'n'
INSERT INTO a VALUES (4, 6);'n'
INSERT INTO a VALUES (2, 7);'n'
INSERT INTO a VALUES (6, 9);'n'
INSERT INTO a VALUES (6, 10);'n'
'n'
-- All good here'n'
INSERT INTO b VALUES (2, 'b', 'Description');'n'
INSERT INTO b VALUES (3, 'c', 'Description'n'
2nd line of description');'n'
INSERT INTO b VALUES (1, 'a', 'Description');'n'
INSERT INTO b VALUES (4, 'd', 'Description'n'
2nd line of description'n'
3rd line of description');'n'
INSERT INTO b VALUES (5, 'e', 'Description');";
/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/document.body.innerHTML='<code><pre></pre></code>';console = {log:function(input){document.getElementsByTagName('pre')[0].innerHTML+=input+''n'}};
var blockRegex = /((?:'bINSERT's+INTO's+[^'s]+'s+VALUES's*'((?:[^"')]+|"[^"'']*(?:''.[^"'']*)*"|'[^''']*(?:''.[^''']*)*')*');['r'n'']*)+)/i,
rowsRegex = /(?:'bINSERT's+INTO's+[^'s]+'s+VALUES's*'((?:[^"')]+|"[^"'']*(?:''.[^"'']*)*"|'[^''']*(?:''.[^''']*)*')*');['r'n'']*)/ig,
result = data.split(blockRegex),
resultRows;
for (var i = 0; i < result.length; i++) {
resultRows = result[i].match(rowsRegex);
if (resultRows) {
resultRows.alphanumSort();
result[i] = resultRows.join('');
}
}
data = result.join('');
console.log(data);
<script src="http://www.davekoelle.com/files/alphanum.js"></script>
备注
这使用了一个自然排序函数:http://www.davekoelle.com/alphanum.html
基于@Shaunt的建议,我更改了脚本,使其使用按表存储的完整语句数组,然后在自定义排序函数中分别解析这些语句。
var parseRow = function(r){
var match = r.match(/VALUES '(('d+)(?:, ('d+|NULL))?[, )]/);
if (!match)
return [];
return [match[1], match[2]];
},
test = /INSERT INTO "?([a-z]+)"?'s*VALUES's*'(('d+),['s'S]+?;/g,
Tables = {},
TableCounters = {};
data.replace(test,function(row,table){
if (typeof Tables[table] !== 'object')
Tables[table] = [];
Tables[table].push(row);
TableCounters[table] = 0;
return row;
});
for (var j = 0, k = Object.keys(Tables), l = k.length; j<l; j++){
var table = k[j];
Tables[table].sort(function(a,b){
a = parseRow(a);
b = parseRow(b);
var ix = 0;
if (a[0] === b[0] && a[1] !== 'NULL' && b[1] !== 'NULL')
ix++;
a[ix] = parseInt(a[ix], 10);
b[ix] = parseInt(b[ix], 10);
return a[ix] > b[ix] ? 1 : (a[ix] < b[ix] ? -1 : 0);
})
}
data = data.replace(test,function(row,table){
var nextRowIndex = TableCounters[table]++;
return Tables[table][nextRowIndex];
});
工作示例:
var data =
"--'n'
-- PostgreSQL database dump'n'
--'n'
'n'
SET statement_timeout = 0;'n'
SET lock_timeout = 0;'n'
SET client_encoding = 'UTF8';'n'
SET standard_conforming_strings = on;'n'
SET check_function_bodies = false;'n'
SET client_min_messages = warning;'n'
'n'
-- Working fine'n'
INSERT INTO c VALUES (3, 'c', 45);'n'
INSERT INTO c VALUES (1, 'a', 11);'n'
INSERT INTO c VALUES (5, 'e', 77);'n'
INSERT INTO c VALUES (4, 'd', 76);'n'
INSERT INTO c VALUES (2, 'b', 33);'n'
'n'
--'n'
-- Name: a; Type: TABLE; Schema: public'n'
--'n'
CREATE TABLE a ('n'
first integer NOT NULL,'n'
second integer NOT NULL'n'
);'n'
'n'
--'n'
-- Name: a_first_second; Type: CONSTRAINT; Schema: public'n'
--'n'
ALTER TABLE ONLY a'n'
ADD CONSTRAINT a_first_second PRIMARY KEY (first, second);'n'
'n'
-- Breaks'n'
INSERT INTO a VALUES (1, 1);'n'
INSERT INTO a VALUES (2, 5);'n'
INSERT INTO a VALUES (4, 2);'n'
INSERT INTO a VALUES (5, 6);'n'
INSERT INTO a VALUES (2, 4);'n'
INSERT INTO a VALUES (3, 7);'n'
INSERT INTO a VALUES (4, 6);'n'
INSERT INTO a VALUES (2, 7);'n'
INSERT INTO a VALUES (6, 9);'n'
'n'
-- All good here'n'
INSERT INTO b VALUES (2, 'b', 'Description');'n'
INSERT INTO b VALUES (3, 'c', 'Description'n'
2nd line of description');'n'
INSERT INTO b VALUES (1, 'a', 'Description');'n'
INSERT INTO b VALUES (4, 'd', 'Description'n'
2nd line of description'n'
3rd line of description');'n'
INSERT INTO b VALUES (5, 'e', 'Description');";
/*//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////*/document.body.innerHTML='<code><pre></pre></code>';console = {log:function(input){document.getElementsByTagName('pre')[0].innerHTML+=input+''n'}};
var parseRow = function(r){
var match = r.match(/VALUES '(('d+)(?:, ('d+|NULL))?[, )]/);
if (!match)
return [];
return [match[1], match[2]];
},
test = /INSERT INTO "?([a-z]+)"?'s*VALUES's*'(('d+),['s'S]+?;/g,
Tables = {},
TableCounters = {};
data.replace(test,function(row,table){
if (typeof Tables[table] !== 'object')
Tables[table] = [];
Tables[table].push(row);
TableCounters[table] = 0;
return row;
});
for (var j = 0, k = Object.keys(Tables), l = k.length; j<l; j++){
var table = k[j];
Tables[table].sort(function(a,b){
a = parseRow(a);
b = parseRow(b);
var ix = 0;
if (a[0] === b[0] && a[1] !== 'NULL' && b[1] !== 'NULL')
ix++;
a[ix] = parseInt(a[ix], 10);
b[ix] = parseInt(b[ix], 10);
return a[ix] > b[ix] ? 1 : (a[ix] < b[ix] ? -1 : 0);
})
}
data = data.replace(test,function(row,table){
var nextRowIndex = TableCounters[table]++;
return Tables[table][nextRowIndex];
});
console.log(data);
相关文章:
- 如何在这里将两个值最低的数字相加
- 计算HTML表TD中两个数字之间的百分比
- 如何使用 JavaScript 将两个数字相加
- 用于添加两个数字的javascript闭包的用法
- 通过变量在两个数字之间切换
- 在数字字符串的最后两个数字上加上小数
- 在HTML/JavaScript中减去两个数字
- 用于获取两个方括号之间的数字的正则表达式
- 把两个数字加在一起,得到5+10=510,而不是15
- 敲除:如何对两个数字输入进行双向绑定
- 正则表达式允许字母数字和空格,但不允许连续两个空格
- 在 JavaScript 中使用最后两个数字获取年份
- 对于大的数字,在这个本地化函数上强制使用两个小数
- javascript中的函数重载使两个函数名称相同,但输入数字不同
- jquery json 返回添加两个数字的数据
- 添加两个数字,并使用Javascript在文本框中显示结果
- 添加两个数字的JavaScript函数工作不正常
- 在JavaScript中递归地添加任意两个数字
- Javascript正则表达式匹配多个单词中至少一个以数字开头的单词,但至少匹配两个单词
- 正则表达式用于验证两个范围之间的数字