JavaScript深度嵌套数组过滤

时间:2018-08-21 03:43:26

标签: javascript arrays



我创建了某种功能的“深度”嵌套数组过滤功能。此功能显示汽车,并为其分配了颜色“红色”。但是,“通过”过滤器的汽车是仅分配了1种颜色的汽车。
如何确保标准中检查了阵列中的阵列?我是否需要在循环内创建循环?理想的结果是,如果将标准设置为“红色”,由于这些汽车也具有此颜色,因此还将显示BMW和SUZUKI。

由于我自己找不到任何非常有用的东西,因此对获得任何帮助,建议或与其他帖子的其他链接以取得理想的结果表示衷心的感谢。该帖子最有用的就是这一篇-Filtering an array with a deeply nested array in JS

在下面,我附上了我当前代码的代码片段。

class TrayTooltip
{
    public static List<string> ScanToolbarButtons()
    {
        List<string> tooltips = new List<string>();

        var handle = GetSystemTrayHandle();
        if (handle == IntPtr.Zero)
        {
            return null;
        }

        var count = SendMessage(handle, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero).ToInt32();
        if (count == 0)
        {
            return null;
        }

        GetWindowThreadProcessId(handle, out var pid);
        var hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
        if (hProcess == IntPtr.Zero)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        var size = (IntPtr)Marshal.SizeOf<TBBUTTONINFOW>();
        var buffer = VirtualAllocEx(hProcess, IntPtr.Zero, size, MEM_COMMIT, PAGE_READWRITE);
        if (buffer == IntPtr.Zero)
        {
            CloseHandle(hProcess);
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        for (int i = 0; i < count; i++)
        {
            var btn = new TBBUTTONINFOW();
            btn.cbSize = size.ToInt32();
            btn.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
            if (WriteProcessMemory(hProcess, buffer, ref btn, size, out var written))
            {
                // we want the identifier
                var res = SendMessage(handle, TB_GETBUTTONINFOW, (IntPtr)i, buffer);
                if (res.ToInt32() >= 0)
                {
                    if (ReadProcessMemory(hProcess, buffer, ref btn, size, out var read))
                    {
                        // now get display text using the identifier
                        // first pass we ask for size
                        var textSize = SendMessage(handle, TB_GETBUTTONTEXTW, (IntPtr)btn.idCommand, IntPtr.Zero);
                        if (textSize.ToInt32() != -1)
                        {
                            // we need to allocate for the terminating zero and unicode
                            var utextSize = (IntPtr)((1 + textSize.ToInt32()) * 2);
                            var textBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, utextSize, MEM_COMMIT, PAGE_READWRITE);
                            if (textBuffer != IntPtr.Zero)
                            {
                                res = SendMessage(handle, TB_GETBUTTONTEXTW, (IntPtr)btn.idCommand, textBuffer);
                                if (res == textSize)
                                {
                                    var localBuffer = Marshal.AllocHGlobal(utextSize.ToInt32());
                                    if (ReadProcessMemory(hProcess, textBuffer, localBuffer, utextSize, out read))
                                    {
                                        var text = Marshal.PtrToStringUni(localBuffer);
                                        tooltips.Add(text);
                                    }
                                    Marshal.FreeHGlobal(localBuffer);
                                }
                                VirtualFreeEx(hProcess, textBuffer, IntPtr.Zero, MEM_RELEASE);
                            }
                        }
                    }
                }
            }
        }

        VirtualFreeEx(hProcess, buffer, IntPtr.Zero, MEM_RELEASE);
        CloseHandle(hProcess);

        return tooltips;
    }

    private static IntPtr GetSystemTrayHandle()
    {
        var hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
        hwnd = FindWindowEx(hwnd, IntPtr.Zero, "TrayNotifyWnd", null);
        hwnd = FindWindowEx(hwnd, IntPtr.Zero, "SysPager", null);
        return FindWindowEx(hwnd, IntPtr.Zero, "ToolbarWindow32", null);
    }

    [DllImport("kernel32", SetLastError = true)]
    private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr hObject);

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref TBBUTTONINFOW lpBuffer, IntPtr nSize, out IntPtr lpNumberOfBytesWritten);

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref TBBUTTONINFOW lpBuffer, IntPtr nSize, out IntPtr lpNumberOfBytesRead);

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, IntPtr nSize, out IntPtr lpNumberOfBytesRead);

    [DllImport("user32", SetLastError = true)]
    private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

    [DllImport("kernel32", SetLastError = true)]
    private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, int flAllocationType, int flProtect);

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, int dwFreeType);

    [DllImport("user32")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32", SetLastError = true)]
    private static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName);

    private const int TBIF_BYINDEX = unchecked((int)0x80000000); // this specifies that the wparam in Get/SetButtonInfo is an index, not id
    private const int TBIF_COMMAND = 0x20;
    private const int MEM_COMMIT = 0x1000;
    private const int MEM_RELEASE = 0x8000;
    private const int PAGE_READWRITE = 0x4;
    private const int TB_GETBUTTONINFOW = 1087;
    private const int TB_GETBUTTONTEXTW = 1099;
    private const int TB_BUTTONCOUNT = 1048;

    private static bool IsWindowsVistaOrAbove() => Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6;
    private static int PROCESS_ALL_ACCESS => IsWindowsVistaOrAbove() ? 0x001FFFFF : 0x001F0FFF;

    [StructLayout(LayoutKind.Sequential)]
    private struct TBBUTTONINFOW
    {
        public int cbSize;
        public int dwMask;
        public int idCommand;
        public int iImage;
        public byte fsState;
        public byte fsStyle;
        public short cx;
        public IntPtr lParam;
        public IntPtr pszText;
        public int cchText;
    }
}
const myCars = [
    { name: "BMW",colour: ["White","Red","Black"] },
    { name: "AUDI",colour: ["Yellow","Silver"] },
    { name: "VW",colour: ["Purple","Gold"] },
    { name: "NISSAN",colour: ["White","Black"] },
    { name: "SUZUKI",colour: ["Red"] }, 
];

for (x in myCars) {
  var keys = Object.keys(myCars[x])

  var carSpec = myCars.filter(function(fltr) {
    return (fltr.colour == "Red");

  });
  document.getElementById("show1").innerHTML += carSpec[x].name + " " + "has these colours - " + carSpec[x].colour + "<hr />";
}

2 个答案:

答案 0 :(得分:4)

您需要对filter数组进行includes测试,colour

const myCars = [
    { name: "BMW",colour: ["White","Red","Black"] },
    { name: "AUDI",colour: ["Yellow","Silver"] },
    { name: "VW",colour: ["Purple","Gold"] },
    { name: "NISSAN",colour: ["White","Black"] },
    { name: "SUZUKI",colour: ["Red"] }, 
];
const show1 = document.getElementById("show1");
myCars
  .filter(({ colour }) => colour.includes('Red'))
  .forEach(({ name, colour }) => {
    show1.innerHTML += name + " " + "has these colours - " + colour + "<hr />";
  });
<p>Car List.</p>

<p id="show"></p>
<p id="show1"></p>

答案 1 :(得分:1)

您可以使用reduce获取一系列可用红色显示的汽车,然后使用forEach对其进行循环并显示文本。

join将通过定界符连接数组的所有内容

const myCars = [{
    name: "BMW",
    colour: ["White", "Red", "Black"]
  },
  {
    name: "AUDI",
    colour: ["Yellow", "Silver"]
  },
  {
    name: "VW",
    colour: ["Purple", "Gold"]
  },
  {
    name: "NISSAN",
    colour: ["White", "Black"]
  },
  {
    name: "SUZUKI",
    colour: ["Red"]
  },

];


let hasRed = myCars.reduce(function(acc, curr) {
  if (curr.colour.indexOf('Red') !== -1) {
    acc.push(curr)
  }
  return acc;

}, []).forEach((item) => {
  document.getElementById("show1").innerHTML += item.name + " " + "has these colours - " + item.colour.join(',') + "<hr />";
})
<p>Car List.</p>

<p id="show"></p>
<p id="show1"></p>