JavaScript过程来查找一个字符串中的字符,但不在另一个字符串中

JavaScript过程来查找一个字符串中的字符,但不在另一个字符串中,javascript,algorithm,Javascript,Algorithm,我一直在试着写一本,但它越来越乱了 假设我有两个字符串textStart,textTarget,我想跟踪我需要从textStart添加和删除的字符,以便生成textTarget 例如,如果textStart=dude和textTarget=deck,则需要添加的字符将是'c'和'k',而需要减除的字符将是'u'和'd'中的一个 我想我首先需要创建表示textStart和textTarget中每个字符数量的映射 所以我写了这个: var startChars = {}; for (

我一直在试着写一本,但它越来越乱了

假设我有两个字符串textStart,textTarget,我想跟踪我需要从textStart添加和删除的字符,以便生成textTarget

例如,如果textStart=dude和textTarget=deck,则需要添加的字符将是'c'和'k',而需要减除的字符将是'u'和'd'中的一个

我想我首先需要创建表示textStart和textTarget中每个字符数量的映射

所以我写了这个:

    var startChars = {};
    for (var k = 0, n = textStart.length; k < n; ++k)
    {
        if (textStart[k] in startChars)
            ++startChars[textStart[k]];
        else
            startChars[textStart[k]] = 1;
    }
    var targetChars = {};
    for (var k = 0, n = textTarget.length; k < n; ++k)
    {
        if (textTarget[k] in startChars)
            ++targetChars[textTarget[k]];
        else
            map1[targetChars[k]] = 1;
    }
我不确定如何按预期填充这些映射,因为我不知道如何使用JavaScript迭代映射的键。我总得有个好结局

需要添加['c']=1, 需要添加['k']=1, 需要删除['u']=1, 需要删除['d']=1

这就是你们进来帮我的地方

我希望我已经很好地描述了我正在尝试做什么,以及到目前为止我是如何尝试去做的。我的编程直觉告诉我,我写的代码太多了,需要向StackOverflow寻求帮助。没有JQuery或Regex,有什么方法可以优雅地实现这一点?我知道有人会在这个线程中编写一个1行正则表达式解决方案或类似的东西。

这里有一个我花了太多时间的问题。。。希望它有意义:

var s = 'dude',
t = 'deck',
finalOutput = '';
for (var i = 0; i < s.length; i++){
    if ( typeof t[i] != 'undefined' ){
        if ( s[i] != t[i] ){
            console.log(s[i] + ' changed to ' + t[i]);
            s[i] = t[i];
            finalOutput += t[i];

        } else{
            finalOutput += s[i];
        }
    }
}
console.log('FINAL: ' + finalOutput);
var textStart = 'dude';
var textTarget = 'deck';

var startChars = {};
for (var k = 0, n = textStart.length; k < n; ++k)
{
    if (textStart[k] in startChars)
        ++startChars[textStart[k]];
    else
        startChars[textStart[k]] = 1;
}

var targetChars = {};
for (var k = 0, n = textTarget.length; k < n; ++k)
{
    if (textTarget[k] in targetChars)
        ++targetChars[textTarget[k]];
    else
        targetChars[textTarget[k]] = 1;
}

console.log('start: ' + JSON.stringify(startChars));
console.log('target: ' + JSON.stringify(targetChars));

var needAdded = {};
var needRemoved = {};

for (var c in startChars) {
    // If target does not contain letter, remove all, otherwise remove excess
    if (targetChars[c] > 0) {
        if (startChars[c] > targetChars[c])
            needRemoved[c] = startChars[c] - targetChars[c];
        else if (startChars[c] < targetChars[c])
            needAdded[c] = targetChars[c] - startChars[c];
    } else {
        needRemoved[c] = startChars[c];
    }
}

for (var c in targetChars) {
    // If start does not contain letter, add all, otherwise add excess
    if (startChars[c] > 0) {
        if (startChars[c] > targetChars[c])
            needRemoved[c] = startChars[c] - targetChars[c];
        else if (startChars[c] < targetChars[c])
            needAdded[c] = targetChars[c] - startChars[c];
    } else {
        needAdded[c] = targetChars[c];
    }
}

console.log('needAdded: ' + JSON.stringify(needAdded));
console.log('needRemoved: ' + JSON.stringify(needRemoved));

好的,这方面的时间也太多了:

var textStart = "dude";
var textTarget = "duck";

var map = {};
MapCharacters(textStart, map, 1);
MapCharacters(textTarget, map, -1);
console.log(map);

var toDelete = [];
var toAdd = [];

for (var prop in map) {
    if (map.hasOwnProperty(prop)) {
        while (map[prop] > 0) {
            toDelete.push(prop);
            map[prop]--;
        }
        while (map[prop] < 0) {
            toAdd.push(prop);
            map[prop]++;
        }

    }
}

console.log(toDelete);
console.log(toAdd);

function MapCharacters(string, map, add) {
    for (var k = 0, n = string.length; k < n; ++k) {
        if (string[k] in map) {
            map[string[k]] += add;
        } else {
            map[string[k]] = add;
        }
    }
}
也许可以更有效地完成,但正如我所说的——时间太多了


我意识到最好的方法不是制作两张地图,而是一张。第一种情况是增加每个字母的计数,第二种情况是减少计数。现在很容易找到哪些需要删除,哪些结束>0,哪些需要添加,哪些结束<0

要循环对象,请使用对象{}中的forvar键。由于代码太多,您可以重构循环以将映射构建为函数,因此只需编写一次。然后按@A.O.的建议用于…。您也可以将其固定在函数中,因为您需要在两个对象中的属性上循环。@user3461018-不,不,一点也不。代码重用只是将相关代码提取到函数中的原因之一。它对可读性、组织性也很有用,我经常发现,强迫自己给一些代码命名的行为极大地帮助我理解我实际上在做什么。@user3461018:不。如果你使用了不止一次,那正是你创建函数的时候。即使只使用一次,有时为了更好地组织代码、使其更可读、更易于维护和推理,将其作为函数也是有意义的。加上那些只有在函数习惯于成为所有其他位置函数时才需要它的函数。多年来,我逐渐相信创建函数最重要的原因就是给一组代码起一个名字。如果你想不出一个简单、简洁的名字,那么你要么真的不知道它到底在做什么,要么它想做的太多了。
start: {"d":2,"u":1,"e":1}
target: {"d":1,"e":1,"c":1,"k":1}
needAdded: {"c":1,"k":1}
needRemoved: {"d":1,"u":1} 
var textStart = "dude";
var textTarget = "duck";

var map = {};
MapCharacters(textStart, map, 1);
MapCharacters(textTarget, map, -1);
console.log(map);

var toDelete = [];
var toAdd = [];

for (var prop in map) {
    if (map.hasOwnProperty(prop)) {
        while (map[prop] > 0) {
            toDelete.push(prop);
            map[prop]--;
        }
        while (map[prop] < 0) {
            toAdd.push(prop);
            map[prop]++;
        }

    }
}

console.log(toDelete);
console.log(toAdd);

function MapCharacters(string, map, add) {
    for (var k = 0, n = string.length; k < n; ++k) {
        if (string[k] in map) {
            map[string[k]] += add;
        } else {
            map[string[k]] = add;
        }
    }
}