将字符串数组排序为对象数组

时间:2015-10-01 21:00:33

标签: javascript arrays

好的,所以我一直在为我的应用程序开发一个排序功能,而且我已经卡住了。

Here's my fiddle.

简要说明一下,此代码以字符串数组serials和空数组displaySerials开头:

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var displaySerials = [];

这些函数的目的是将displaySerials输出为具有两个属性的对象数组:beginSerialendSerial。它的工作方式是函数循环遍历数组,并尝试在一个范围内相互设置每个兼容的字符串,然后从该范围创建beginSerial是最低序列号的对象在范围内,endSerial是范围最高的。

为了澄清,连续范围内的所有序列都将具有相同的前缀。一旦建立了该前缀,则将字符串与前缀分开并进行数字比较和排序。

因此,基于此,数组serials的所需输出将是:

displaySerials = [
    { beginSerial: "BHU-008", endSerial: "BHU-011" },
    { beginSerial: "BHU-000", endSerial: "BHU-002" },
    { beginSerial: "TYU-969", endSerial: "TYU-970" }
]

我主要处理我的jsfiddle,唯一的问题是该函数正在将一个重复的对象推入数组中,而且我不确定如何通过我的检查。< / p>

非常感谢任何帮助。

5 个答案:

答案 0 :(得分:1)

这里没有什么太复杂,但它应该做的伎俩。请注意,我正在从一开始就对数组进行排序,因此我可以可靠地迭代它。

小提琴在这里:http://jsfiddle.net/qyys9vw1/

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var myNewObjectArray = [];
var sortedSerials = serials.sort();

//seed the object
var myObject = {};
var previous = sortedSerials[0];
var previousPrefix = previous.split("-")[0];
var previousValue = previous.split("-")[1];
myObject.beginSerial = previous;
myObject.endSerial = previous;

//iterate watching for breaks in the sequence
for (var i=1; i < sortedSerials.length; i++) {
    var current = sortedSerials[i];
    console.log(current);
    var currentPrefix = current.split("-")[0];
    var currentValue = current.split("-")[1];
    if (currentPrefix === previousPrefix && parseInt(currentValue) === parseInt(previousValue)+1) {
        //sequential value found, so update the endSerial with it
        myObject.endSerial = current;
        previous = current;
        previousPrefix = currentPrefix;
        previousValue = currentValue;
    } else {
        //sequence broken; push the object
        console.log(currentPrefix, previousPrefix, parseInt(currentValue), parseInt(previousValue)+1);
        myNewObjectArray.push(myObject);

        //re-seed a new object
        previous = current;
        previousPrefix = currentPrefix;
        previousValue = currentValue;
        myObject = {};
        myObject.beginSerial = current;
        myObject.endSerial = current;
    }
}
myNewObjectArray.push(myObject); //one final push
console.log(myNewObjectArray);

答案 1 :(得分:1)

Marc的解决方案是正确的,但我无法帮助他们认为代码太多了。这是完全相同的事情,从sort()开始,然后使用reduce()获得更优雅的外观。

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"]

serials.sort()
var first = serials.shift()
var ranges = [{begin: first, end: first}]
serials.reduce(mergeRange, ranges[0])
console.log(ranges) // the expected result

// and this is the reduce callback:

function mergeRange(lastRange, s)
{
    var parts = s.split(/-/)
    var lastParts = lastRange.end.split(/-/)

    if (parts[0] === lastParts[0] && parts[1]-1 === +lastParts[1]) {
        lastRange.end = s
        return lastRange
    } else {
        var newRange = {begin: s, end: s}
        ranges.push(newRange)
        return newRange
    }
}

我感觉有可能在没有排序的情况下做到这一点,通过递归合并在数组的小块上获得的结果(比较两个元素,然后将结果合并两个,依此类推,直到你有一个结果数组)。代码看起来不太好,但它可以更好地扩展,并且可以并行完成。

答案 2 :(得分:0)

我会将underscore.js用于此

var bSerialExists = _.findWhere(displaySerials, { beginSerial: displaySettings.beginSerial });
var eSerialExists = _.findWhere(displaySerials, { endSerial: displaySettings.endSerial });

if (!bSerialExists && !eSerialExists)
    displaySerials.push(displaySettings);

答案 3 :(得分:0)

这是一个用普通JavaScript执行此操作的函数。

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];

function transformSerials(a) {
  var result = []; //store array for result
  var holder = {}; //create a temporary object

  //loop the input array and group by prefix
  a.forEach(function(val) {
    var parts = val.split('-');
    var type = parts[0];
    var int = parseInt(parts[1], 10);
    
    if (!holder[type])
      holder[type] = { prefix : type, values : [] };
    
    holder[type].values.push({ name : val, value : int });
  });
  
  //interate through the temp object and find continuous values
  for(var type in holder) {
    var last = null;
    var groupHolder = {};
    
    //sort the values by integer
    var numbers = holder[type].values.sort(function(a,b) {
      return parseInt(a.value, 10) > parseInt(b.value, 10);
    });
    
    numbers.forEach(function(value, index) {
      if (!groupHolder.beginSerial)
        groupHolder.beginSerial = value.name;
        
      if (!last || value.value === last + 1) {
        last = value.value;
        groupHolder.endSerial = value.name;
        if (index === numbers.length - 1) {
          result.push(groupHolder);
        }
      }
      else {
        result.push(groupHolder);
        groupHolder = {};
        last = null;
      }
    });
    
  }
  return result;
}

console.log(transformSerials(serials));
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

答案 4 :(得分:0)

我最终解决了自己的问题,因为我比我想象的要近得多。在初始排序完成后,我包含了最终排序以消除重复的对象。

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];

var displaySerials = [];


var mapSerialsForDisplay = function () {
    var tempArray = serials;

    displaySerials = [];

    for (var i = 0; i < tempArray.length; i++) {
        // compare current member to all other members for similarity
        var currentSerial = tempArray[i];
        var range = [currentSerial];

        var displaySettings = {
            beginSerial: currentSerial,
            endSerial: ""
        }

        for (var j = 0; j < tempArray.length; j++) {
            if (i === j) {
                continue;
            } else {
                var stringInCommon = "";
                var comparingSerial = tempArray[j];

                for (var n = 0; n < currentSerial.length; n++) {
                    if (currentSerial[n] === comparingSerial[n]) {
                        stringInCommon += currentSerial[n];
                        continue;
                    } else {
                        var currentRemaining = currentSerial.replace(stringInCommon, "");
                        var comparingRemaining = comparingSerial.replace(stringInCommon, "");

                        if (!isNaN(currentRemaining) && !isNaN(comparingRemaining) && stringInCommon !== "") {
                            range = compareAndAddToRange(comparingSerial, stringInCommon, range);
                            displaySettings.beginSerial = range[0];
                            displaySettings.endSerial = range[range.length - 1];

                            var existsAlready = false;

                            for (var l = 0; l < displaySerials.length; l++) {


                                if (displaySerials[l].beginSerial == displaySettings.beginSerial || displaySerials[l].endSerial == displaySettings.endSerial) {
                                    existsAlready = true;
                                }
                            }

                            if (!existsAlready) {
                                displaySerials.push(displaySettings);
                            }
                        }
                    }
                }
            }
        }
    }

    for (var i = 0; i < displaySerials.length; i++) {
        for (var j = 0; j < displaySerials.length; j++) {
            if (i === j) {
                continue;
            } else {
                if (displaySerials[i].beginSerial === displaySerials[j].beginSerial && displaySerials[i].endSerial === displaySerials[j].endSerial) {
                    displaySerials.splice(j, 1);
                }
            }
        }
    }

    return displaySerials;
}

var compareAndAddToRange = function (candidate, commonString, arr) {
    var tempArray = [];

    for (var i = 0; i < arr.length; i++) {
        tempArray.push({
            value: arr[i],
            number: parseInt(arr[i].replace(commonString, ""))
        });
    }

    tempArray.sort(function(a, b) { 
        return (a.number > b.number) ? 1 : ((b.number > a.number) ? -1 : 0); 
    });

    var newSerial = {
        value: candidate,
        number: candidate.replace(commonString, "")
    }

    if (tempArray.indexOf(newSerial) === -1) {
        if (tempArray[0].number - newSerial.number === 1) {
            tempArray.unshift(newSerial)
        } else if (newSerial.number - tempArray[tempArray.length - 1].number === 1) {
            tempArray.push(newSerial);
        }
    }

    for (var i = 0; i < tempArray.length; i++) {
        arr[i] = tempArray[i].value;
    }

    arr.sort();

    return arr;
}

mapSerialsForDisplay();
console.log(displaySerials);

fiddle to see it work