重命名数组JavaScript中的重复项

时间:2017-07-29 01:58:15

标签: javascript arrays string object rename

我正在寻求帮助来解决重命名数组中字符串的问题,如下所示:

["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]

执行函数后,它应如下所示:

["a(1)","a(6)","a","a(2)","a(3)","a(4)","a(5)","a(7)","a(8)","a(9)","a(10)","a(11)"]

没有重复的空数组和数组应保持不变。

我的想法是使用键/值对填充空对象,然后将它们推送到新数组:

function renameFiles(arr){
    var itemsObj = {};
    var count = 1;
    for (var i = 0; i < arr.length; i++){

        itemsObj[arr[i]] = count;
        // if the key present, rename the array item and add it to the 
        // itemsObj
        if (arr[i] in itemsObj){
            itemsObj[arr[i] + '(' + (i - (i - 1)) + ')']
        }

    }
    console.log(itemsObj)
    // once the itmesObj is set, run the loop and push the keys to the 
    // array
    return arr;

}

var array = ["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]
renameFiles(array);

问题是itemsObj没有填充重复键。应该有一些其他方法可以处理此任务。我是初学者,可能不知道那种方法。

4 个答案:

答案 0 :(得分:1)

你几乎就在那里。您要保留计数,并检查重复项,然后再检查带括号的重复项,并适当更新计数

&#13;
&#13;
function renameFiles(arr){
  var count = {};
  arr.forEach(function(x,i) {

    if ( arr.indexOf(x) !== i ) {
      var c = x in count ? count[x] = count[x] + 1 : count[x] = 1;
      var j = c + 1;
      var k = x + '(' + j + ')';

      while( arr.indexOf(k) !== -1 ) k = x + '(' + (++j) + ')';
      arr[i] = k;
    }
  });
  return arr;
}

var res = renameFiles(["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]);
console.log(res)
&#13;
.as-console-wrapper {top:0; max-height:100%!important}
&#13;
&#13;
&#13;

答案 1 :(得分:1)

你走在正确的轨道上。

另一种解决方案,

(function(){
    var renameFiles = function(arr){
        var counts = {}
        for(var i=0;i<arr.length;i++){
            if(!counts[arr[i]])
                counts[arr[i]]=0;
            counts[arr[i]]++;
        }
        arr = [];
        for(var name in counts){
            for(var i=0;i<counts[name];i++){
                arr.push(name+(i===0?'':'('+i+')'));
            }
        }
        return arr;
    }

    var array = ["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"];
    console.log(renameFiles(array))
})();

答案 2 :(得分:0)

var arr = ["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]

function renameFiles(arr){
  var dup_count, new_name;
  arr.forEach((item, index) => {
    dup_count = arr.filter(x => x == item).length;
    if (dup_count > 1) {
      for(n = 0; n < dup_count;){
        do {
          new_name = `${item}(${n+=1})`;
        } while (arr.includes(new_name));
        arr[arr.indexOf(item)] = new_name;
      }
    }
  });
  return arr
}
> renameFiles(arr)
< (12) ["a(1)", "a(6)", "a(2)", "a(3)", "a(4)", "a(5)", "a(7)", "a(8)", "a(9)", "a(10)", "a(11)", "a"]

答案 3 :(得分:0)

要获得相同的结果而不会发生突变,可以使用以下代码。尽管代码更多,但我包含的大多数功能都可以用Ramda或另一个FP库包含的功能代替。我发现以下内容更具可读性,但这只是一个简单的偏好问题。

工作沙箱here

const incrementingList = (n) => [...Array(n).keys()];
const formatStr = (key) => ifElse(equals(0))(always(key))(concat(key));

const incValues = (obj) =>
  flatMap((key) => map(formatStr(key))(incrementingList(obj[key])))(keys(obj));

const incOrInit = (record, key) =>
  isNil(record[key])
    ? assoc(key)(1)(record)
    : assoc(key)(inc(record[key]))(record);

const generateCounts = reduce({})(incOrInit);
const renameList = compose(incValues, generateCounts);

const list = ["a", "b", "b", "b", "a", "a", "c", "c", "c", "d"];
const result = renameList(list);
console.log(result); // => ["a", "a1", "a2", "b", "b1", "b2", "c", "c1", "c2", "d"]

// THESE FUNCTIONS CAN BE REPLACE WITH RAMDA \\

function keys(obj) {
  return Object.keys(obj);
}

function ifElse(cond) {
  return function ifTrueFn(trueFn) {
    return function ifFalseFn(falseFn) {
      return function passValue(value) {
        return cond(value) ? trueFn(value) : falseFn(value);
      };
    };
  };
}

function always(value) {
  return function alwaysInner() {
    return value;
  };
}

function concat(a) {
  return function inner(b) {
    return a.concat(b);
  };
}

function equals(a) {
  return function equalsInner(b) {
    return a === b;
  };
}

function compose2(fn1, fn2) {
  return function passArg(...args) {
    return fn1(fn2(...args));
  };
}

function compose(...fns) {
  return fns.reduce(compose2);
}

function flatMap(mapFn) {
  return function inner(list) {
    return list.flatMap(mapFn);
  };
}

function map(mapFn) {
  return function passList(list) {
    return list.map(mapFn);
  };
}

function reduce(init) {
  return function reducer(reducer) {
    return function data(data) {
      return data.reduce(reducer, init);
    };
  };
}

function assoc(key) {
  return function assocValue(value) {
    return function assocObject(obj) {
      return { ...obj, [key]: value };
    };
  };
}

function inc(n) {
  return n + 1;
}

function isNil(value) {
  return value == null;
}