比较多个对象值和操作节点,

Comparing multiple Object values and manipulating nodes,

预期功能: 创建一个 new 数组,该数组改变对象数组中的值。新值将是对象,其键 value 是原始值,另一个键 duplicate 是布尔值,如果该值与同一位置的其他对象值相同。

我试图循环数组,然后创建另一个数组,其中包含不是当前索引的索引。

创建一个不影响原始输入的深拷贝,然后循环原始数组,每次循环都会捕获当前对象的key。

我没有尝试更改任何比第一个范围更深的值,这就是为什么我只是改变 typeof !== "object"

然后我设置当前索引,并将键设置为一个新对象,其中 value 将保持原始值,但 duplicate 将成为其他索引的映射,比较到当前索引,然后使用 .some 方法缩减为单个布尔值。

设置好深拷贝中的每个值后,return它。

我目前正在尝试创建一个数组,其中包含不是当前索引的索引。

const testState = [
  {
    value1: "1",
    value2: "two",
    value3: 3,
  },
  {
    value1: "one",
    value2: 2,
    value3: "3",
  },
  {
    value1: "1",
    value2: 2,
    value3: "3",
  },
];

const testEquality = (accountArray) => {
  // Deep copy (shallow copies were letting values change)
  const returnedArray = JSON.parse(JSON.stringify(accountArray));

  accountArray.forEach((account) => {
    // assign an array that contains ever other index
    const otherIndexes = [];
    for (const key in account) {
      if (typeof key !== "object") {
        returnedArray[i][key] = {
          value: accountArray[i][key],
          // loop every other index, and compare to accountArray[i][key]
          // ex: otherIndexes.map(index => accountArray[index][key] === accountArray[i][key]).some(i => i)
          duplicate: false,
        };
      }
    }
  });

  return returnedArray;
};

testState = testState.map((obj) => testEquality(obj));

console.log(testState);
// output
[
  {
    value1: { value: "1", duplicate: true },
    value2: { value: "two", duplicate: false },
    value3: { value: 3, duplicate: false },
  },
  {
    value1: { value: "one", duplicate: false },
    value2: { value: 2, duplicate: true },
    value3: { value: "3", duplicate: true },
  },
  {
    value1: { value: "1", duplicate: true },
    value2: { value: 2, duplicate: true },
    value3: { value: "3", duplicate: true },
  },
];

我不在整个重构之上,但被告知这太低效了,我已经尝试过不同的方法,这只是我得到的最接近的方法。

如果我对问题的理解正确,我相信这就是他们的目标。首先创建所有值的映射,然后将这些值插入输出数组。您遇到的麻烦是由于使用 Array.some 的额外循环造成的。区别是 O(n)O(n^2).

const testState = [{
    value1: "1",
    value2: "two",
    value3: 3,
  },
  {
    value1: "one",
    value2: 2,
    value3: "3",
  },
  {
    value1: "1",
    value2: 2,
    value3: "3",
  },
];

function testEquality(array) {
  const copy = JSON.parse(JSON.stringify(array));
  const map = new Map();
  for (let i = 0; i < array.length; i++) {
    const values = Object.values(copy[i]);
    values.forEach(entry => {
      if (!map.has(entry)) {
        map.set(entry, false); // new value, not a duplicate
      } else {
        map.set(entry, true); // we've seen it before mark it as duplicate
      }
    });
  }
  for (let i = 0; i < copy.length; i++) {
    const entry = copy[i];
    for (const key in entry) {
      entry[key] = {
        value: array[i][key],
        duplicate: map.get(array[i][key])
      };
    }
  }
  return copy;
}

console.log(testEquality(testState));

const testState = [
  {
    value1: "1",
    value2: "two",
    value3: 3,
  },
  {
    value1: "one",
    value2: 2,
    value3: "3",
  },
  {
    value1: "1",
    value2: 2,
    value3: "3",
  },
];

function transformData(array) {

  const { arr, duplicates } = array.reduce(({ arr, duplicates }, current) => {
    arr.push(
      Object.entries(current).map(([key, value]) => {
        duplicates.push(value);
        return [key, { value }];
      })
    );

    return {
      arr,
      duplicates,
    };
  }, { arr: [], duplicates: [] });

  return arr.reduce((finalArr, cur) => {
    finalArr.push(
      cur.reduce((obj, [nameKey, { value }]) => {
        const duplicatesQty = duplicates.filter(x => x === value).length;
        obj[nameKey] = { value, duplicate: duplicatesQty > 1 ? true : false };
        return obj;
      }, {})
    );

    return finalArr;
  }, []);
}

const test = [
  {
    value1: { value: "1", duplicate: true },
    value2: { value: "two", duplicate: false },
    value3: { value: 3, duplicate: false },
  },
  {
    value1: { value: "one", duplicate: false },
    value2: { value: 2, duplicate: true },
    value3: { value: "3", duplicate: true },
  },
  {
    value1: { value: "1", duplicate: true },
    value2: { value: 2, duplicate: true },
    value3: { value: "3", duplicate: true },
  },
];


console.assert(JSON.stringify(test) === JSON.stringify(transformData(testState)), 'true assert, shouldnt print!');
console.assert(JSON.stringify(test) !== JSON.stringify(transformData(testState)), 'validation confirmation, this should print');

可能有很多方法可以做到这一点...这就是我要做的...

感谢大家的帮助!我忘记指定一个边缘情况,其中节点值 可以 相同,并且不被认为是重复的,因为它们在对象中处于不同的位置。

我的回答还不是很有效,有时间我会尝试重构。然而,更重要的是这个功能的工作超过了它的性能。

这是我的工作

const testEquality = (accountArray) => {
  // deep copy to prevent original array from being effected
  const returnedArray = JSON.parse(JSON.stringify(accountArray));

  accountArray.forEach((account, i) => {

    // array that specifies every other index, besides this one
    const otherIndexes = accountArray
      .map((_, index) => index)
      .filter((index) => i !== index);
    
    for (const key in account) {
    
      // to keep this algorithm from leaving the scope 
      if (typeof key !== "object") {
    
        returnedArray[i][key] = {
          value: accountArray[i][key],
    
          // loop every other index, and compare to accountArray[i][key]
          duplicate: otherIndexes
            .map((index) => accountArray[index][key] === accountArray[i][key])
            .some((i) => i),
        };

      }
    }
  });

  return returnedArray;
};

又来了!谢谢!当人们回答我的问题时,我总是很兴奋